<div dir="ltr"><div class="gmail_extra"><br><div class="gmail_quote">On Tue, Sep 9, 2014 at 4:54 PM, Steve Borho <span dir="ltr"><<a href="mailto:steve@borho.org" target="_blank">steve@borho.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div><div>On 09/09, <a href="mailto:sagar@multicorewareinc.com" target="_blank">sagar@multicorewareinc.com</a> wrote:<br>
> # HG changeset patch<br>
> # User Sagar Kotecha <<a href="mailto:sagar@multicorewareinc.com" target="_blank">sagar@multicorewareinc.com</a>><br>
> # Date 1410252991 -19800<br>
> #      Tue Sep 09 14:26:31 2014 +0530<br>
> # Node ID e546a7da6d486e1bc6c6da09ce7188a5796dff34<br>
> # Parent  3c02887100033f399135f2a774d8253eecb971e3<br>
> cli: add cli options analysis-out and analysis-in<br>
><br>
> analysis-out - dump the intra/inter information into file<br>
> analysis-in -  read the intra/inter information from file<br>
><br>
> diff -r 3c0288710003 -r e546a7da6d48 source/common/param.cpp<br>
> --- a/source/common/param.cpp Tue Sep 09 14:24:11 2014 +0530<br>
> +++ b/source/common/param.cpp Tue Sep 09 14:26:31 2014 +0530<br>
> @@ -724,6 +724,8 @@<br>
>          p->rc.bStatRead = pass & 2;<br>
>      }<br>
>      OPT("stats") p->rc.statFileName = strdup(value);<br>
> +    OPT("analysis-out") p->bAnalysisDataOut = atobool(value);<br>
> +    OPT("analysis-in") p->bAnalysisDataIn = atobool(value);<br>
>      else<br>
>          return X265_PARAM_BAD_NAME;<br>
>  #undef OPT<br>
> @@ -1023,6 +1025,8 @@<br>
>            "Constant rate-factor is incompatible with 2pass");<br>
>      CHECK(param->rc.rateControlMode == X265_RC_CQP && param->rc.bStatRead,<br>
>            "Constant QP is incompatible with 2pass");<br>
> +    CHECK((param->bAnalysisDataIn == 1 && param->bAnalysisDataOut == 1),<br>
><br>
</div></div>our coding style is more like:<br>
       CHECK((param->bAnalysisDataIn && param->bAnalysisDataOut),<br>
<span><br>
> +        "analysis-out and analysis-in options can not go together\n");<br>
<br>
</span>white-space, and also: why not?<br>
<span><br>
>      return check_failed;<br>
>  }<br>
><br>
> diff -r 3c0288710003 -r e546a7da6d48 source/x265.cpp<br>
> --- a/source/x265.cpp Tue Sep 09 14:24:11 2014 +0530<br>
> +++ b/source/x265.cpp Tue Sep 09 14:26:31 2014 +0530<br>
> @@ -202,6 +202,8 @@<br>
>      { "pass",           required_argument, NULL, 0 },<br>
>      { "slow-firstpass",       no_argument, NULL, 0 },<br>
>      { "no-slow-firstpass",    no_argument, NULL, 0 },<br>
> +    { "analysis-out",   required_argument, NULL, 0 },<br>
> +    { "analysis-in",    required_argument, NULL, 0 },<br>
<br>
</span>required_argument?<br>
<div><div><br>
>      { 0, 0, 0, 0 }<br>
>  };<br>
><br>
> @@ -229,6 +231,7 @@<br>
>      int64_t prevUpdateTime;<br>
>      float   frameRate;<br>
>      FILE*   qpfile;<br>
> +    FILE*   analysisFile;<br>
><br>
>      /* in microseconds */<br>
>      static const int UPDATE_INTERVAL = 250000;<br>
> @@ -245,6 +248,7 @@<br>
>          prevUpdateTime = 0;<br>
>          bDither = false;<br>
>          qpfile = NULL;<br>
> +        analysisFile = NULL;<br>
>      }<br>
><br>
>      void destroy();<br>
> @@ -254,6 +258,8 @@<br>
>      void showHelp(x265_param *param);<br>
>      bool parse(int argc, char **argv, x265_param* param);<br>
>      bool parseQPFile(x265_picture &pic_org);<br>
> +    void readAnalysisFile(x265_picture* pic, x265_param*);<br>
> +    void writeAnalysisFile(x265_picture* pic, x265_param*);<br>
>  };<br>
><br>
>  void CLIOptions::destroy()<br>
> @@ -267,6 +273,9 @@<br>
>      if (qpfile)<br>
>          fclose(qpfile);<br>
>      qpfile = NULL;<br>
> +    if (analysisFile)<br>
> +        fclose(analysisFile);<br>
> +    analysisFile = NULL;<br>
>  }<br>
><br>
>  void CLIOptions::writeNALs(const x265_nal* nal, uint32_t nalcount)<br>
> @@ -468,6 +477,8 @@<br>
>      H0("\nReconstructed video options (debugging):\n");<br>
>      H0("-r/--recon <filename>            Reconstructed raw image YUV or Y4M output file name\n");<br>
>      H0("   --recon-depth <integer>       Bit-depth of reconstructed raw image file. Defaults to input bit depth, or 8 if Y4M\n");<br>
> +    H0("   --analysis-out                Frames intra/inter analysis info dumped into file. (each frame data is dumped into its own file, each file is named with its #poc \n");<br>
> +    H0("   --analysis-in                 Intra-Inter analysis info is read from file. (each frame data is read from its own file, expected each file named with its #poc \n");<br>
<br>
</div></div>these two options don't belong under "Reconstructed video options".<br>
They belong with the two-pass options or under their own heading<br>
<br>
Also, we need a patch in this series which bumps X265_BUILD and adds<br>
documentation for these two new options.<br>
<span><br>
>  #undef OPT<br>
>  #undef H0<br>
>      printf("\n\nFull documentation may be found at <a href="http://x265.readthedocs.org/en/default/cli.html%5Cn" target="_blank">http://x265.readthedocs.org/en/default/cli.html\n</a>");<br>
> @@ -728,6 +739,68 @@<br>
>      return false;<br>
>  }<br>
><br>
> +void CLIOptions::readAnalysisFile(x265_picture* pic, x265_param* p)<br>
> +{<br>
> +    char fname[10];<br>
> +    sprintf(fname, "%d", pic->poc);<br>
> +    this->analysisFile = fopen(fname, "rb");<br>
<br>
</span>a file per frame is kind of brutal, we'll need some mechanism for using<br>
a single analysis file. either by making each record a fixed size, or<br>
scanning ahead to find the record you need.<br>
<div><div><br>
> +    if (this->analysisFile)<br>
> +    {<br>
> +        int poc, width, height;<br>
> +        fscanf(this->analysisFile, "%dx%d %d %d %d %d\n", &width, &height, &poc, &pic->sliceType, &pic->intraInterData.numCUsInFrame, &pic->intraInterData.numPartitions);<br>
> +        if (poc != pic->poc || width != p->sourceWidth || height != p->sourceHeight)<br>
> +        {<br>
> +            x265_log(NULL, X265_LOG_WARNING, "Error in reading intra-inter data.\n");<br>
> +            x265_free_inter_intra_data(pic);<br>
> +            return;<br>
> +        }<br>
> +        if (pic->sliceType == X265_TYPE_I || pic->sliceType == X265_TYPE_IDR)<br>
> +        {<br>
> +            fread(pic->intraInterData.intraData->depth, sizeof(uint8_t), pic->intraInterData.numPartitions * pic->intraInterData.numPartitions, this->analysisFile);<br>
> +            fread(pic->intraInterData.intraData->modes, sizeof(uint8_t), pic->intraInterData.numPartitions * pic->intraInterData.numPartitions, this->analysisFile);<br>
> +            fread(pic->intraInterData.intraData->partSizes, sizeof(char), pic->intraInterData.numPartitions * pic->intraInterData.numPartitions, this->analysisFile);<br>
> +            fread(pic->intraInterData.intraData->poc, sizeof(int), pic->intraInterData.numCUsInFrame, this->analysisFile);<br>
> +            fread(pic->intraInterData.intraData->cuAddr, sizeof(uint32_t), pic->intraInterData.numCUsInFrame, this->analysisFile);<br>
> +        }<br>
> +        else<br>
> +            fread(pic->intraInterData.interData, sizeof(x265_inter_data), pic->intraInterData.numCUsInFrame * 85, this->analysisFile);<br>
> +    }<br>
> +    else<br>
> +    {<br>
> +        x265_log(NULL, X265_LOG_WARNING, "Error in opening file to read analysis data.\n");<br>
> +        x265_free_inter_intra_data(pic);<br>
> +    }<br>
> +}<br>
> +<br>
> +void CLIOptions::writeAnalysisFile(x265_picture* pic, x265_param *p)<br>
> +{<br>
> +    char fname[10];<br>
> +    sprintf(fname, "%d", pic->poc);<br>
> +    this->analysisFile = fopen(fname, "wb");<br>
> +    if (this->analysisFile)<br>
> +    {<br>
> +        fprintf(this->analysisFile, "%dx%d %d %d %d %d\n", p->sourceWidth, p->sourceHeight, pic->poc, pic->sliceType, pic->intraInterData.numCUsInFrame, pic->intraInterData.numPartitions);<br>
> +        if (pic->sliceType == X265_TYPE_I || pic->sliceType == X265_TYPE_IDR)<br>
> +        {<br>
> +            fwrite(pic->intraInterData.intraData->depth,<br>
> +                sizeof(uint8_t), pic->intraInterData.numPartitions * pic->intraInterData.numCUsInFrame, this->analysisFile);<br>
> +            fwrite(pic->intraInterData.intraData->modes,<br>
> +                sizeof(uint8_t), pic->intraInterData.numPartitions * pic->intraInterData.numCUsInFrame, this->analysisFile);<br>
> +            fwrite(pic->intraInterData.intraData->partSizes,<br>
> +                sizeof(char), pic->intraInterData.numPartitions * pic->intraInterData.numCUsInFrame, this->analysisFile);<br>
> +            fwrite(pic->intraInterData.intraData->poc, sizeof(int), pic->intraInterData.numCUsInFrame, this->analysisFile);<br>
> +            fwrite(pic->intraInterData.intraData->cuAddr, sizeof(uint32_t), pic->intraInterData.numCUsInFrame, this->analysisFile);<br>
> +        }<br>
> +        else<br>
> +            fwrite(pic->intraInterData.interData, sizeof(x265_inter_data), pic->intraInterData.numCUsInFrame * 85, this->analysisFile);<br>
> +    }<br>
> +    else<br>
> +    {<br>
> +        x265_log(NULL, X265_LOG_WARNING, "Error in opening file to write analysis data.\n");<br>
> +        x265_free_inter_intra_data(pic);<br>
> +    }<br>
> +}<br>
> +<br>
>  bool CLIOptions::parseQPFile(x265_picture &pic_org)<br>
>  {<br>
>      int32_t num = -1, qp, ret;<br>
> @@ -820,6 +893,13 @@<br>
><br>
>      x265_picture_init(param, pic_in);<br>
><br>
> +    if ((param->bAnalysisDataOut || param->bAnalysisDataIn) && !pic_recon)<br>
> +    {<br>
> +        x265_log(NULL, X265_LOG_WARNING, "Must specify recon with analysis-out or analysis-in options, Disabling --analysis-out, --analysis-in\n");<br>
<br>
</div></div>hmm, that's unfortunate.  it would be better if the encoder filled in<br>
the output picture struct if a recon picture is enabled or if<br>
bAnalysisDataOut is enabled. then this check would not be necessary.<br>
<span><br>
> +        param->bAnalysisDataOut = false;<br>
> +        param->bAnalysisDataIn = false;<br>
<br>
</span>how does this affect the input side?<br></blockquote><div><br></div><div>we delete the analysis buffer only through the pic_recon (once the encoding is done the analysis buffers are given to pic_recon which latter used to release the respective pic_in analysis buffers (We don't copy or maintain separate copy of analysis buffer inside the encoder)).</div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
<span><br>
> +    }<br>
> +<br>
>      if (cliopt.bDither)<br>
>      {<br>
>          errorBuf = X265_MALLOC(int16_t, param->sourceWidth + 1);<br>
> @@ -856,6 +936,16 @@<br>
>              pic_in->bitDepth = X265_DEPTH;<br>
>          }<br>
><br>
> +        if ((param->bAnalysisDataIn || param->bAnalysisDataOut) && pic_in)<br>
<br>
</span>this looks like a bug, should it be checking bAnalysisDataOut here?<br>
<div><div><br></div></div></blockquote><div>We allocate the memory for the pic_in and point it out through recon for dumping</div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div><div>
> +        {<br>
> +            x265_alloc_inter_intra_data(pic_in, param);<br>
> +<br>
> +            if (param->bAnalysisDataIn)<br>
> +                cliopt.readAnalysisFile(pic_in, param);<br>
> +        }<br>
> +        else if (param->bAnalysisDataOut && pic_in)<br>
> +            x265_alloc_inter_intra_data(pic_in, param);<br>
> +<br>
>          int numEncoded = x265_encoder_encode(encoder, &p_nal, &nal, pic_in, pic_recon);<br>
>          if (numEncoded < 0)<br>
>          {<br>
> @@ -866,6 +956,12 @@<br>
>          if (numEncoded && pic_recon)<br>
>          {<br>
>              cliopt.recon->writePicture(pic_out);<br>
> +            if (param->bAnalysisDataIn || param->bAnalysisDataOut)<br>
> +            {<br>
> +                if (pic_recon->intraInterData.interData)<br>
> +                    cliopt.writeAnalysisFile(pic_recon, param);<br>
> +                x265_free_inter_intra_data(pic_recon);<br>
> +            }<br>
>          }<br>
><br>
>          if (nal)<br>
> @@ -883,6 +979,12 @@<br>
>          if (numEncoded && pic_recon)<br>
>          {<br>
>              cliopt.recon->writePicture(pic_out);<br>
> +            if (param->bAnalysisDataIn || param->bAnalysisDataOut)<br>
> +            {<br>
> +                if (param->bAnalysisDataOut)<br>
> +                    cliopt.writeAnalysisFile(pic_recon, param);<br>
> +                x265_free_inter_intra_data(pic_recon);<br>
<br>
</div></div>this would be much simpler as just two if expressions<br>
<br>
> +            }<br>
>          }<br>
><br>
>          if (nal)<br>
> _______________________________________________<br>
> x265-devel mailing list<br>
> <a href="mailto:x265-devel@videolan.org" target="_blank">x265-devel@videolan.org</a><br>
> <a href="https://mailman.videolan.org/listinfo/x265-devel" target="_blank">https://mailman.videolan.org/listinfo/x265-devel</a><br>
<span><font color="#888888"><br>
--<br>
Steve Borho<br>
_______________________________________________<br>
x265-devel mailing list<br>
<a href="mailto:x265-devel@videolan.org" target="_blank">x265-devel@videolan.org</a><br>
<a href="https://mailman.videolan.org/listinfo/x265-devel" target="_blank">https://mailman.videolan.org/listinfo/x265-devel</a><br>
</font></span></blockquote></div><br></div></div>