+ if (p->bDistributeModeAnalysis && p->analysisMode)
+ {
+ p->analysisMode = X265_ANALYSIS_OFF;
+ x265_log(p, X265_LOG_WARNING, "Analysis save and load mode not supported for distributed mode analysis\n");
+ }
+}
+
+void Encoder::allocAnalysis(x265_analysis_data* analysis)
+{
+ if (analysis->sliceType == X265_TYPE_IDR || analysis->sliceType == X265_TYPE_I)
+ {
+ analysis_intra_data *intraData = (analysis_intra_data*)analysis->intraData;
+ CHECKED_MALLOC_ZERO(intraData, analysis_intra_data, 1);
+ CHECKED_MALLOC(intraData->depth, uint8_t, analysis->numPartitions * analysis->numCUsInFrame);
+ CHECKED_MALLOC(intraData->modes, uint8_t, analysis->numPartitions * analysis->numCUsInFrame);
+ CHECKED_MALLOC(intraData->partSizes, char, analysis->numPartitions * analysis->numCUsInFrame);
+ analysis->intraData = intraData;
+ }
+ else
+ {
+ analysis_inter_data *interData = (analysis_inter_data*)analysis->interData;
+ CHECKED_MALLOC(interData, analysis_inter_data, analysis->numCUsInFrame * X265_MAX_PRED_MODE_PER_CTU * 2);
+ analysis->interData = interData;
+ }
+ return;
+
+fail:
+ freeAnalysis(analysis);
+ m_aborted = true;
+}
+
+void Encoder::freeAnalysis(x265_analysis_data* analysis)
+{
+ if (analysis->sliceType == X265_TYPE_IDR || analysis->sliceType == X265_TYPE_I)
+ {
+ X265_FREE(((analysis_intra_data*)analysis->intraData)->depth);
+ X265_FREE(((analysis_intra_data*)analysis->intraData)->modes);
+ X265_FREE(((analysis_intra_data*)analysis->intraData)->partSizes);
+ X265_FREE(analysis->intraData);
+ }
+ else
+ X265_FREE(analysis->interData);
+}
+
+void Encoder::readAnalysisFile(x265_analysis_data* analysis, int curPoc)
+{
+
+#define X265_FREAD(val, size, readSize, fileOffset)\
+ if (fread(val, size, readSize, fileOffset) != readSize)\
+ {\
+ x265_log(NULL, X265_LOG_ERROR, "Error reading analysis data\n");\
+ freeAnalysis(analysis);\
+ m_aborted = true;\
+ return;\
+ }\
+
+ static uint64_t consumedBytes = 0;
+ static uint64_t totalConsumedBytes = 0;
+ fseeko(m_analysisFile, totalConsumedBytes, SEEK_SET);
+
+ int poc; uint32_t frameRecordSize;
+ X265_FREAD(&frameRecordSize, sizeof(uint32_t), 1, m_analysisFile);
+ X265_FREAD(&poc, sizeof(int), 1, m_analysisFile);
+
+ uint64_t currentOffset = totalConsumedBytes;
+
+ /* Seeking to the right frame Record */
+ while (poc != curPoc && !feof(m_analysisFile))
+ {
+ currentOffset += frameRecordSize;
+ fseeko(m_analysisFile, currentOffset, SEEK_SET);
+ X265_FREAD(&frameRecordSize, sizeof(uint32_t), 1, m_analysisFile);
+ X265_FREAD(&poc, sizeof(int), 1, m_analysisFile);
+ }
+
+ if (poc != curPoc || feof(m_analysisFile))
+ {
+ x265_log(NULL, X265_LOG_WARNING, "Error reading analysis data: Cannot find POC %d\n", curPoc);
+ freeAnalysis(analysis);
+ return;
+ }
+
+ /* Now arrived at the right frame, read the record */
+ analysis->poc = poc;
+ analysis->frameRecordSize = frameRecordSize;
+ X265_FREAD(&analysis->sliceType, sizeof(int), 1, m_analysisFile);
+ X265_FREAD(&analysis->numCUsInFrame, sizeof(int), 1, m_analysisFile);
+ X265_FREAD(&analysis->numPartitions, sizeof(int), 1, m_analysisFile);
+
+ /* Memory is allocated for inter and intra analysis data based on the slicetype */
+ allocAnalysis(analysis);
+
+ if (analysis->sliceType == X265_TYPE_IDR || analysis->sliceType == X265_TYPE_I)
+ {
+ X265_FREAD(((analysis_intra_data *)analysis->intraData)->depth, sizeof(uint8_t), analysis->numCUsInFrame * analysis->numPartitions, m_analysisFile);
+ X265_FREAD(((analysis_intra_data *)analysis->intraData)->modes, sizeof(uint8_t), analysis->numCUsInFrame * analysis->numPartitions, m_analysisFile);
+ X265_FREAD(((analysis_intra_data *)analysis->intraData)->partSizes, sizeof(char), analysis->numCUsInFrame * analysis->numPartitions, m_analysisFile);
+ analysis->sliceType = X265_TYPE_I;
+ consumedBytes += frameRecordSize;
+ }
+ else if (analysis->sliceType == X265_TYPE_P)
+ {
+ X265_FREAD(analysis->interData, sizeof(analysis_inter_data), analysis->numCUsInFrame * X265_MAX_PRED_MODE_PER_CTU, m_analysisFile);
+ consumedBytes += frameRecordSize;
+ totalConsumedBytes = consumedBytes;
+ }
+ else
+ {
+ X265_FREAD(analysis->interData, sizeof(analysis_inter_data), analysis->numCUsInFrame * X265_MAX_PRED_MODE_PER_CTU * 2, m_analysisFile);
+ consumedBytes += frameRecordSize;
+ }
+#undef X265_FREAD
+}
+
+void Encoder::writeAnalysisFile(x265_analysis_data* analysis)
+{
+
+#define X265_FWRITE(val, size, writeSize, fileOffset)\
+ if (fwrite(val, size, writeSize, fileOffset) < writeSize)\
+ {\
+ x265_log(NULL, X265_LOG_ERROR, "Error writing analysis data\n");\
+ freeAnalysis(analysis);\
+ m_aborted = true;\
+ return;\
+ }\
+
+ /* calculate frameRecordSize */
+ analysis->frameRecordSize = sizeof(analysis->frameRecordSize) + sizeof(analysis->poc) + sizeof(analysis->sliceType) +
+ sizeof(analysis->numCUsInFrame) + sizeof(analysis->numPartitions);
+ if (analysis->sliceType == X265_TYPE_IDR || analysis->sliceType == X265_TYPE_I)
+ analysis->frameRecordSize += sizeof(uint8_t) * analysis->numCUsInFrame * analysis->numPartitions * 3;
+ else if (analysis->sliceType == X265_TYPE_P)
+ analysis->frameRecordSize += sizeof(analysis_inter_data) * analysis->numCUsInFrame * X265_MAX_PRED_MODE_PER_CTU;
+ else
+ analysis->frameRecordSize += sizeof(analysis_inter_data) * analysis->numCUsInFrame * X265_MAX_PRED_MODE_PER_CTU * 2;
+
+ X265_FWRITE(&analysis->frameRecordSize, sizeof(uint32_t), 1, m_analysisFile);
+ X265_FWRITE(&analysis->poc, sizeof(int), 1, m_analysisFile);
+ X265_FWRITE(&analysis->sliceType, sizeof(int), 1, m_analysisFile);
+ X265_FWRITE(&analysis->numCUsInFrame, sizeof(int), 1, m_analysisFile);
+ X265_FWRITE(&analysis->numPartitions, sizeof(int), 1, m_analysisFile);
+
+ if (analysis->sliceType == X265_TYPE_IDR || analysis->sliceType == X265_TYPE_I)
+ {
+ X265_FWRITE(((analysis_intra_data*)analysis->intraData)->depth, sizeof(uint8_t), analysis->numCUsInFrame * analysis->numPartitions, m_analysisFile);
+ X265_FWRITE(((analysis_intra_data*)analysis->intraData)->modes, sizeof(uint8_t), analysis->numCUsInFrame * analysis->numPartitions, m_analysisFile);
+ X265_FWRITE(((analysis_intra_data*)analysis->intraData)->partSizes, sizeof(char), analysis->numCUsInFrame * analysis->numPartitions, m_analysisFile);
+ }
+ else if (analysis->sliceType == X265_TYPE_P)
+ {
+ X265_FWRITE(analysis->interData, sizeof(analysis_inter_data), analysis->numCUsInFrame * X265_MAX_PRED_MODE_PER_CTU, m_analysisFile);
+ }
+ else
+ {
+ X265_FWRITE(analysis->interData, sizeof(analysis_inter_data), analysis->numCUsInFrame * X265_MAX_PRED_MODE_PER_CTU * 2, m_analysisFile);
+ }
+#undef X265_FWRITE