图片转载于x265源码流程分析_Dillon2015的博客-CSDN博客_x265编码流程

cliopt.prase

main ()函数——解析函数参数并进行编码准备工作:x265.cpp
(1)GetConsoleTitle(orgConsoleTitle, CONSOLE_TITLE_SIZE):获取控制台窗口
(2)cliopt.parse()函数:解析参数,直接调用可打印输入视频的详细信息
(3)api->encoder_open()函数:打开编码器配置
(4)api->encoder_headers()函数:设置NAL相关信息
(5)api->encoder_encode()函数:进入编码函数
(6)api->encoder_close()函数:结束编码并进行总结

encoder_open()函数、encoder_headers()函数、encoder_encode()函数与encoder_close()函数均位于api.app中
参考:https://yq.aliyun.com/articles/31058

main()函数中的部分功能函数的详细功能

1. CLIOptions结构体 : x265 的各种参数主要是通过CLIOptions结构体及相关函数传递给x265的各API

参考x265源码分析:main函数及CLIOptions结构体解释_nk_wavelet的博客-CSDN博客_x265源码

/* 命令行接口 */
struct CLIOptions
{InputFile*  input;          // 输入文件,抽象类, 定义在 \input\input.h 中ReconFile*  recon;          // 重构文件,抽象类,定义在 \output\output.h 中OutputFile* output;         // 输出文件,抽象类,定义在 \output\output.h 中FILE*       qpfile;         // 量化因子文件指针FILE*       csvfpt;         // csv日志文件指针const char* csvfn;          // csv日志文件名const char* reconPlayCmd;   const x265_api* api;        // x265_param* param;          // x265编码器参数集bool bProgress;             // 是否输出编码进度和其他一些编码状态数据bool bForceY4m;             // 如果输入文件是Y4M格式,需要强制指定输入格式bool bDither;int csvLogLevel;            // csv日志级别,log level定义在 x265.h中uint32_t seek;              // 输入视频起始需要跳过的帧数uint32_t framesToBeEncoded; // 待编码的帧数uint64_t totalbytes;        // 已编码的数据字节数int64_t startTime;          // 起始编码时间点int64_t prevUpdateTime;     // 上一次编码信息输出的时间点/* in microseconds,相邻两次编码状态输出的最小时间间隔,单位微妙 */static const int UPDATE_INTERVAL = 250000;// 构造函数,初始化上述各成员变量CLIOptions(){… … … … }void destroy();void printStatus(uint32_t frameNum);        // 打印编码状态信息bool parse(int argc, char **argv);          // 解释命令行参数bool parseQPFile(x265_picture &pic_org);    // 解释量化因子QP文件
};/* 打印编码状态信息 */
void CLIOptions::printStatus(uint32_t frameNum)
{char buf[200];int64_t time = x265_mdate();// 是否输出编码状态信息取决于:进度开关、当前编码帧数、上次信息输出和当前时间的间隔if (!bProgress || !frameNum || (prevUpdateTime && time - prevUpdateTime < UPDATE_INTERVAL))return;// 计算编码帧率和码率int64_t elapsed = time - startTime;double fps = elapsed > 0 ? frameNum * 1000000. / elapsed : 0;float bitrate = 0.008f * totalbytes * (param->fpsNum / param->fpsDenom) / ((float)frameNum);if (framesToBeEncoded){int eta = (int)(elapsed * (framesToBeEncoded - frameNum) / ((int64_t)frameNum * 1000000));sprintf(buf, "x265 [%.1f%%] %d/%d frames, %.2f fps, %.2f kb/s, eta %d:%02d:%02d", 100. * frameNum / framesToBeEncoded, frameNum, framesToBeEncoded, fps, bitrate, eta / 3600, (eta / 60) % 60, eta % 60);}elsesprintf(buf, "x265 %d frames: %.2f fps, %.2f kb/s", frameNum, fps, bitrate);fprintf(stderr, "%s  \r", buf + 5);SetConsoleTitle(buf);fflush(stderr);             // needed in windowsprevUpdateTime = time;
}

2.cliopt.parse(argc, argv) 

cliopt.parse(argc, argv)的主要功能是分析參数,直接调用x265.cpp中的bool CLIOptions::parse(int argc, char **argv)函数,该函数会打印输入视频的分辨率、帧率、视频格式、所要编码的帧数目以及输出文件名等。

bool CLIOptions::parse(int argc, char **argv)
{bool bError = false;int bShowHelp = false;int inputBitDepth = 8;int outputBitDepth = 0;int reconFileBitDepth = 0;const char *inputfn = NULL;const char *reconfn = NULL;const char *outputfn = NULL;const char *preset = NULL;const char *tune = NULL;const char *profile = NULL;if (argc <= 1){x265_log(NULL, X265_LOG_ERROR, "No input file. Run x265 --help for a list of options.\n");return true;}/* Presets are applied before all other options. */for (optind = 0;; ){int c = getopt_long(argc, argv, short_options, long_options, NULL);if (c == -1)break;else if (c == 'p')preset = optarg;else if (c == 't')tune = optarg;else if (c == 'D')outputBitDepth = atoi(optarg);else if (c == 'P')profile = optarg;else if (c == '?')bShowHelp = true;}if (!outputBitDepth && profile){/* try to derive the output bit depth from the requested profile */if (strstr(profile, "10"))outputBitDepth = 10;else if (strstr(profile, "12"))outputBitDepth = 12;elseoutputBitDepth = 8;}api = x265_api_get(outputBitDepth);if (!api){x265_log(NULL, X265_LOG_WARNING, "falling back to default bit-depth\n");api = x265_api_get(0);}param = api->param_alloc();if (!param){x265_log(NULL, X265_LOG_ERROR, "param alloc failed\n");return true;}if (api->param_default_preset(param, preset, tune) < 0){x265_log(NULL, X265_LOG_ERROR, "preset or tune unrecognized\n");return true;}if (bShowHelp){printVersion(param, api);showHelp(param);}for (optind = 0;; ){int long_options_index = -1;int c = getopt_long(argc, argv, short_options, long_options, &long_options_index);if (c == -1)break;switch (c){case 'h':printVersion(param, api);showHelp(param);break;case 'V':printVersion(param, api);x265_report_simd(param);exit(0);default:if (long_options_index < 0 && c > 0){for (size_t i = 0; i < sizeof(long_options) / sizeof(long_options[0]); i++){if (long_options[i].val == c){long_options_index = (int)i;break;}}if (long_options_index < 0){/* getopt_long might have already printed an error message */if (c != 63)x265_log(NULL, X265_LOG_WARNING, "internal error: short option '%c' has no long option\n", c);return true;}}if (long_options_index < 0){x265_log(NULL, X265_LOG_WARNING, "short option '%c' unrecognized\n", c);return true;}
#define OPT(longname) \else if (!strcmp(long_options[long_options_index].name, longname))
#define OPT2(name1, name2) \else if (!strcmp(long_options[long_options_index].name, name1) || \!strcmp(long_options[long_options_index].name, name2))if (0) ;OPT2("frame-skip", "seek") this->seek = (uint32_t)x265_atoi(optarg, bError);OPT("frames") this->framesToBeEncoded = (uint32_t)x265_atoi(optarg, bError);OPT("csv") this->csvfn = optarg;OPT("csv-log-level") this->csvLogLevel = x265_atoi(optarg, bError);OPT("no-progress") this->bProgress = false;OPT("output") outputfn = optarg;OPT("input") inputfn = optarg;OPT("recon") reconfn = optarg;OPT("input-depth") inputBitDepth = (uint32_t)x265_atoi(optarg, bError);OPT("dither") this->bDither = true;OPT("recon-depth") reconFileBitDepth = (uint32_t)x265_atoi(optarg, bError);OPT("y4m") this->bForceY4m = true;OPT("profile") /* handled above */;OPT("preset")  /* handled above */;OPT("tune")    /* handled above */;OPT("output-depth")   /* handled above */;OPT("recon-y4m-exec") reconPlayCmd = optarg;OPT("qpfile"){this->qpfile = fopen(optarg, "rb");if (!this->qpfile){x265_log(param, X265_LOG_ERROR, "%s qpfile not found or error in opening qp file\n", optarg);return false;}}elsebError |= !!api->param_parse(param, long_options[long_options_index].name, optarg);if (bError){const char *name = long_options_index > 0 ? long_options[long_options_index].name : argv[optind - 2];x265_log(NULL, X265_LOG_ERROR, "invalid argument: %s = %s\n", name, optarg);return true;}
#undef OPT}}if (optind < argc && !inputfn)inputfn = argv[optind++];if (optind < argc && !outputfn)outputfn = argv[optind++];if (optind < argc){x265_log(param, X265_LOG_WARNING, "extra unused command arguments given <%s>\n", argv[optind]);return true;}if (argc <= 1){api->param_default(param);printVersion(param, api);showHelp(param);}if (!inputfn || !outputfn){x265_log(param, X265_LOG_ERROR, "input or output file not specified, try --help for help\n");return true;}if (param->internalBitDepth != api->bit_depth){x265_log(param, X265_LOG_ERROR, "Only bit depths of %d are supported in this build\n", api->bit_depth);return true;}InputFileInfo info;info.filename = inputfn;info.depth = inputBitDepth;info.csp = param->internalCsp;info.width = param->sourceWidth;info.height = param->sourceHeight;info.fpsNum = param->fpsNum;info.fpsDenom = param->fpsDenom;info.sarWidth = param->vui.sarWidth;info.sarHeight = param->vui.sarHeight;info.skipFrames = seek;info.frameCount = 0;getParamAspectRatio(param, info.sarWidth, info.sarHeight);this->input = InputFile::open(info, this->bForceY4m);if (!this->input || this->input->isFail()){x265_log(param, X265_LOG_ERROR, "unable to open input file <%s>\n", inputfn);return true;}if (info.depth < 8 || info.depth > 16){x265_log(param, X265_LOG_ERROR, "Input bit depth (%d) must be between 8 and 16\n", inputBitDepth);return true;}/* Unconditionally accept height/width/csp from file info */param->sourceWidth = info.width;param->sourceHeight = info.height;param->internalCsp = info.csp;/* Accept fps and sar from file info if not specified by user */if (param->fpsDenom == 0 || param->fpsNum == 0){param->fpsDenom = info.fpsDenom;param->fpsNum = info.fpsNum;}if (!param->vui.aspectRatioIdc && info.sarWidth && info.sarHeight)setParamAspectRatio(param, info.sarWidth, info.sarHeight);if (this->framesToBeEncoded == 0 && info.frameCount > (int)seek)this->framesToBeEncoded = info.frameCount - seek;param->totalFrames = this->framesToBeEncoded;/* Force CFR until we have support for VFR */info.timebaseNum = param->fpsDenom;info.timebaseDenom = param->fpsNum;if (api->param_apply_profile(param, profile))return true;if (param->logLevel >= X265_LOG_INFO){char buf[128];int p = sprintf(buf, "%dx%d fps %d/%d %sp%d", param->sourceWidth, param->sourceHeight,param->fpsNum, param->fpsDenom, x265_source_csp_names[param->internalCsp], info.depth);int width, height;getParamAspectRatio(param, width, height);if (width && height)p += sprintf(buf + p, " sar %d:%d", width, height);if (framesToBeEncoded <= 0 || info.frameCount <= 0)strcpy(buf + p, " unknown frame count");elsesprintf(buf + p, " frames %u - %d of %d", this->seek, this->seek + this->framesToBeEncoded - 1, info.frameCount);general_log(param, input->getName(), X265_LOG_INFO, "%s\n", buf);}this->input->startReader();if (reconfn){if (reconFileBitDepth == 0)reconFileBitDepth = param->internalBitDepth;this->recon = ReconFile::open(reconfn, param->sourceWidth, param->sourceHeight, reconFileBitDepth,param->fpsNum, param->fpsDenom, param->internalCsp);if (this->recon->isFail()){x265_log(param, X265_LOG_WARNING, "unable to write reconstructed outputs file\n");this->recon->release();this->recon = 0;}elsegeneral_log(param, this->recon->getName(), X265_LOG_INFO,"reconstructed images %dx%d fps %d/%d %s\n",param->sourceWidth, param->sourceHeight, param->fpsNum, param->fpsDenom,x265_source_csp_names[param->internalCsp]);}this->output = OutputFile::open(outputfn, info);if (this->output->isFail()){x265_log(param, X265_LOG_ERROR, "failed to open output file <%s> for writing\n", outputfn);return true;}general_log(param, this->output->getName(), X265_LOG_INFO, "output file: %s\n", outputfn);return false;  //完毕后返回false
}

3. parseQPFile(x265_picture &pic_org);    // 解释量化因子QP文件

QP:量化参数(通过调整量化参数QP,以达到调整输出目标码率的目的。 什么是QP ** 量化参数(QP): 1、QP量化参数,反映了空间细节压缩情况,如QP小 ,大部分的细节都会被保留;QP增大,一些细节丢失

bool CLIOptions::parseQPFile(x265_picture &pic_org)
{int32_t num = -1, qp, ret;char type;uint32_t filePos;pic_org.forceqp = 0;pic_org.sliceType = X265_TYPE_AUTO;while (num < pic_org.poc){filePos = ftell(qpfile);qp = -1;ret = fscanf(qpfile, "%d %c%*[ \t]%d\n", &num, &type, &qp);if (num > pic_org.poc || ret == EOF){fseek(qpfile, filePos, SEEK_SET);break;}if (num < pic_org.poc && ret >= 2)continue;if (ret == 3 && qp >= 0)pic_org.forceqp = qp + 1;if (type == 'I') pic_org.sliceType = X265_TYPE_IDR;else if (type == 'i') pic_org.sliceType = X265_TYPE_I;else if (type == 'P') pic_org.sliceType = X265_TYPE_P;else if (type == 'B') pic_org.sliceType = X265_TYPE_BREF;else if (type == 'b') pic_org.sliceType = X265_TYPE_B;else ret = 0;if (ret < 2 || qp < -1 || qp > 51)return 0;}return 1;
}

3. main 主函数

/*=============================================================*/
/* CLI return codes:** 0 - encode successful* 1 - unable to parse command line* 2 - unable to open encoder* 3 - unable to generate stream headers* 4 - encoder abort* 5 - unable to open csv file**/
int main(int argc, char **argv) //主函数入口
{
#if HAVE_VLD// This uses Microsoft's proprietary WCHAR type, but this only builds on Windows to start withVLDSetReportOptions(VLD_OPT_REPORT_TO_DEBUGGER | VLD_OPT_REPORT_TO_FILE, L"x265_leaks.txt");
#endifPROFILE_INIT();THREAD_NAME("API", 0);GetConsoleTitle(orgConsoleTitle, CONSOLE_TITLE_SIZE);  //获取控制台窗体SetThreadExecutionState(ES_CONTINUOUS | ES_SYSTEM_REQUIRED | ES_AWAYMODE_REQUIRED);ReconPlay* reconPlay = NULL;CLIOptions cliopt;if (cliopt.parse(argc, argv))    //==========分析參数。对编码器的參数进行设定,打开文件{cliopt.destroy();if (cliopt.api)cliopt.api->param_free(cliopt.param);exit(1);}x265_param* param = cliopt.param;const x265_api* api = cliopt.api;/* This allows muxers to modify bitstream format */cliopt.output->setParam(param);if (cliopt.reconPlayCmd)reconPlay = new ReconPlay(cliopt.reconPlayCmd, *param);/* note: we could try to acquire a different libx265 API here based on* the profile found during option parsing, but it must be done before* opening an encoder */x265_encoder *encoder = api->encoder_open(param);    //==========encoder_open()函数,打印编码器配置if (!encoder)  //若打不开编码器配置。提示错误{x265_log(param, X265_LOG_ERROR, "failed to open encoder\n");cliopt.destroy();api->param_free(param);api->cleanup();exit(2);}/* get the encoder parameters post-initialization */api->encoder_parameters(encoder, param);if (cliopt.csvfn){cliopt.csvfpt = x265_csvlog_open(*api, *param, cliopt.csvfn, cliopt.csvLogLevel);if (!cliopt.csvfpt){x265_log(param, X265_LOG_ERROR, "Unable to open CSV log file <%s>, aborting\n", cliopt.csvfn);cliopt.destroy();if (cliopt.api)cliopt.api->param_free(cliopt.param);exit(5);}}/* Control-C handler *///当键入Ctrl-C的时候,当前运行程序调用指针函数sigint_handler 运行完后,再返回原来运行的地方接着往下走。if (signal(SIGINT, sigint_handler) == SIG_ERR)x265_log(param, X265_LOG_ERROR, "Unable to register CTRL+C handler: %s\n", strerror(errno));x265_picture pic_orig, pic_out;      //定义x265的输入pic_orig和输出pic_outx265_picture *pic_in = &pic_orig; //获取x265的输入pic_orig的地址/* Allocate recon picture if analysisMode is enabled */std::priority_queue<int64_t>* pts_queue = cliopt.output->needPTS() ? new std::priority_queue<int64_t>() : NULL;x265_picture *pic_recon = (cliopt.recon || !!param->analysisMode || pts_queue || reconPlay || cliopt.csvLogLevel) ?&pic_out : NULL;uint32_t inFrameCount = 0;  //输入的帧数uint32_t outFrameCount = 0; //输出的帧数x265_nal *p_nal;x265_stats stats;uint32_t nal;int16_t *errorBuf = NULL;int ret = 0;if (!param->bRepeatHeaders){if (api->encoder_headers(encoder, &p_nal, &nal) < 0)   //==========encoder_headers函数{x265_log(param, X265_LOG_ERROR, "Failure generating stream headers\n");ret = 3;goto fail;}elsecliopt.totalbytes += cliopt.output->writeHeaders(p_nal, nal);}api->picture_init(param, pic_in);if (cliopt.bDither){errorBuf = X265_MALLOC(int16_t, param->sourceWidth + 1);if (errorBuf)memset(errorBuf, 0, (param->sourceWidth + 1) * sizeof(int16_t));elsecliopt.bDither = false;}// main encoder loop(编码主循环)while (pic_in && !b_ctrl_c){pic_orig.poc = inFrameCount;if (cliopt.qpfile){if (!cliopt.parseQPFile(pic_orig)){x265_log(NULL, X265_LOG_ERROR, "can't parse qpfile for frame %d\n", pic_in->poc);fclose(cliopt.qpfile);cliopt.qpfile = NULL;}}//当输入帧将要所有编码且输入的帧数大于或等于将要编码的帧数if (cliopt.framesToBeEncoded && inFrameCount >= cliopt.framesToBeEncoded)pic_in = NULL;else if (cliopt.input->readPicture(pic_orig))  //每读入一帧inFrameCount++;    //输入的帧数自加1elsepic_in = NULL;if (pic_in){if (pic_in->bitDepth > param->internalBitDepth && cliopt.bDither){x265_dither_image(*api, *pic_in, cliopt.input->getWidth(), cliopt.input->getHeight(), errorBuf, param->internalBitDepth);pic_in->bitDepth = param->internalBitDepth;}/* Overwrite PTS */pic_in->pts = pic_in->poc;}//进行编码的入口函数,读入24帧后才開始编码int numEncoded = api->encoder_encode(encoder, &p_nal, &nal, pic_in, pic_recon); //==========encoder_encode()函数。numEncoded是将要编码的帧数if (numEncoded < 0){b_ctrl_c = 1;ret = 4;break;}if (reconPlay && numEncoded)reconPlay->writePicture(*pic_recon);outFrameCount += numEncoded;if (numEncoded && pic_recon && cliopt.recon)cliopt.recon->writePicture(pic_out);if (nal){cliopt.totalbytes += cliopt.output->writeFrame(p_nal, nal, pic_out);if (pts_queue){pts_queue->push(-pic_out.pts);if (pts_queue->size() > 2)pts_queue->pop();}}cliopt.printStatus(outFrameCount); //打印编码帧的详细信息if (numEncoded && cliopt.csvLogLevel)x265_csvlog_frame(cliopt.csvfpt, *param, *pic_recon, cliopt.csvLogLevel);}/* Flush the encoder *//*功能:前面读入24帧后才開始编码,此处事实上就是处理相应的倒数的24帧,将其存储*/while (!b_ctrl_c) //退出上一个大循环后且没有按下Ctrl+C,代码继续运行{//==========encoder_encode()函数int numEncoded = api->encoder_encode(encoder, &p_nal, &nal, NULL, pic_recon);if (numEncoded < 0){ret = 4;break;}if (reconPlay && numEncoded)reconPlay->writePicture(*pic_recon);outFrameCount += numEncoded;if (numEncoded && pic_recon && cliopt.recon)cliopt.recon->writePicture(pic_out);if (nal){cliopt.totalbytes += cliopt.output->writeFrame(p_nal, nal, pic_out);if (pts_queue){pts_queue->push(-pic_out.pts);if (pts_queue->size() > 2)pts_queue->pop();}}cliopt.printStatus(outFrameCount);if (numEncoded && cliopt.csvLogLevel)x265_csvlog_frame(cliopt.csvfpt, *param, *pic_recon, cliopt.csvLogLevel);if (!numEncoded)break;}/* clear progress report */if (cliopt.bProgress)fprintf(stderr, "%*s\r", 80, " ");fail:delete reconPlay;api->encoder_get_stats(encoder, &stats, sizeof(stats));if (cliopt.csvfpt && !b_ctrl_c)x265_csvlog_encode(cliopt.csvfpt, *api, *param, stats, cliopt.csvLogLevel, argc, argv);api->encoder_close(encoder);    //==========encoder_close()函数int64_t second_largest_pts = 0;int64_t largest_pts = 0;if (pts_queue && pts_queue->size() >= 2){second_largest_pts = -pts_queue->top();pts_queue->pop();largest_pts = -pts_queue->top();pts_queue->pop();delete pts_queue;pts_queue = NULL;}cliopt.output->closeFile(largest_pts, second_largest_pts);if (b_ctrl_c)   //按下Ctrl+C,直接退出general_log(param, NULL, X265_LOG_INFO, "aborted at input frame %d, output frame %d\n",cliopt.seek + inFrameCount, stats.encodedPictureCount);api->cleanup(); /* Free library singletons */cliopt.destroy();api->param_free(param);X265_FREE(errorBuf);SetConsoleTitle(orgConsoleTitle);    //设置控制窗体标题SetThreadExecutionState(ES_CONTINUOUS);#if HAVE_VLDassert(VLDReportLeaks() == 0);
#endifreturn ret;
}

功能分析

1.GetConsoleTitle的主要功能是获取控制台窗体。当中orgConsoleTitle指向一个缓冲区指针以接收包括标题的字符串。CONSOLE_TITLE_SIZE)是由orgConsoleTitle指向的缓冲区大小。假设函数成功。则返回值是以字符为单位的长度控制台窗体的标题;假设该函数失败,则返回值为零。要获取错误信息。能够调用GetLastError 。

2. 调用encoder_open()函数

x265_encoder *encoder = api->encoder_open(param);

encoder_open(param)的主要功能是打印编码器的配置信息,直接调用api.cpp中的x265_encoder *x265_encoder_open(x265_param *p),该函数中调用了x265_print_params(param)用以打印编码器配置信息

相应的代码例如以下:

x265_encoder *x265_encoder_open(x265_param *p)
{if (!p)return NULL;#if _MSC_VER
#pragma warning(disable: 4127) // conditional expression is constant, yes I know
#endif#if HIGH_BIT_DEPTHif (X265_DEPTH == 12)x265_log(p, X265_LOG_WARNING, "Main12 is HIGHLY experimental, do not use!\n");else if (X265_DEPTH != 10 && X265_DEPTH != 12)
#elseif (X265_DEPTH != 8)
#endif{x265_log(p, X265_LOG_ERROR, "Build error, internal bit depth mismatch\n");return NULL;}Encoder* encoder = NULL;x265_param* param = PARAM_NS::x265_param_alloc();x265_param* latestParam = PARAM_NS::x265_param_alloc();if (!param || !latestParam)goto fail;memcpy(param, p, sizeof(x265_param));x265_log(param, X265_LOG_INFO, "HEVC encoder version %s\n", PFX(version_str));x265_log(param, X265_LOG_INFO, "build info %s\n", PFX(build_info_str));x265_setup_primitives(param);if (x265_check_params(param))goto fail;if (x265_set_globals(param))goto fail;encoder = new Encoder;if (!param->rc.bEnableSlowFirstPass)PARAM_NS::x265_param_apply_fastfirstpass(param);// may change params for auto-detect, etcencoder->configure(param);// may change rate control and CPB paramsif (!enforceLevel(*param, encoder->m_vps))goto fail;// will detect and set profile/tier/level in VPSdetermineLevel(*param, encoder->m_vps);if (!param->bAllowNonConformance && encoder->m_vps.ptl.profileIdc == Profile::NONE){x265_log(param, X265_LOG_INFO, "non-conformant bitstreams not allowed (--allow-non-conformance)\n");goto fail;}encoder->create();encoder->m_latestParam = latestParam;memcpy(latestParam, param, sizeof(x265_param));if (encoder->m_aborted)goto fail;x265_print_params(param);   //打印參数return encoder;fail:delete encoder;PARAM_NS::x265_param_free(param);PARAM_NS::x265_param_free(latestParam);return NULL;
}

3.encoder_headers()函数: 设置NAL相关信息

api->encoder_headers(encoder, &p_nal, &nal)

具体代码如下:

int x265_encoder_headers(x265_encoder *enc, x265_nal **pp_nal, uint32_t *pi_nal)
{if (pp_nal && enc){Encoder *encoder = static_cast<Encoder*>(enc);Entropy sbacCoder;Bitstream bs;encoder->getStreamHeaders(encoder->m_nalList, sbacCoder, bs); //get Stream Headers*pp_nal = &encoder->m_nalList.m_nal[0];if (pi_nal) *pi_nal = encoder->m_nalList.m_numNal;return encoder->m_nalList.m_occupancy;}return -1;
}

4. encoder_encode()函数: 进入编码函数

x265源码分析 main函数 x265.cpp相关推荐

  1. jQuery源码分析-each函数

    本文部分截取自且行且思 jQuery.each方法用于遍历一个数组或对象,并对当前遍历的元素进行处理,在jQuery使用的频率非常大,下面就这个函数做了详细讲解: 复制代码代码 /*! * jQuer ...

  2. SRS4.0源码分析-main

    本文采用的 SRS 版本是 4.0-b8 , 下载地址:github 本文开始讲解 SRS 的入口文件.SRS 源码里 其实有 3 个 main() 函数,分别在 srs_main_ingest_hl ...

  3. redis源码之main()函数剖析

    今天看了redis的源码之中的main()函数,将大概的流程进行梳理. 在代码中进行了相应的注释,便于阅读者理解: int main(int argc, char **argv) {struct ti ...

  4. GCC源码分析(十) — 函数节点的gimple高端化

    版权声明:本文为CSDN博主「ashimida@」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明. 原文链接:https://blog.csdn.net/lidan1 ...

  5. GCC源码分析(十一) — 函数节点的gimple低端化

    版权声明:本文为CSDN博主「ashimida@」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明. 原文链接:https://blog.csdn.net/lidan1 ...

  6. 【Linux 内核 内存管理】mmap 系统调用源码分析 ④ ( do_mmap 函数执行流程 | do_mmap 函数源码 )

    文章目录 一.do_mmap 函数执行流程 二.do_mmap 函数源码 调用 mmap 系统调用 , 先检查 " 偏移 " 是否是 " 内存页大小 " 的 & ...

  7. c++imread 函数_OpenCV学习笔记与源码分析: imread( )函数

    引言 imread()函数在opencv使用比较. imread()函数 声明: Mat imread(const string& filename, int flags); 这很标准的写法, ...

  8. x265源码分析:main函数及CLIOptions结构体解释

    /** * 返回码信息:* 0 – 编码成功:* 1 – 命令行解释失败:* 2 – 编码器打开失败:* 3 – 生成流头部失败:* 4 – 编码出错:* 5 – 打开csv文件失败.*/ int m ...

  9. x265源码分析:SAO 函数总结及逻辑关系图

    /** * @brief 边界补偿模式下像素的5种分类 : * 第1类谷点和第2类凹拐点,需要加上一个正补偿值: * 第4类峰点和第3类凸拐点,需要加上一个负补偿值: * 第0类像素不进行补偿. */ ...

最新文章

  1. 百亿级数据分表后怎么分页查询?
  2. [Beta]第五次 Scrum Meeting
  3. 售前工程师的成长(五)---一个老员工的经验之谈
  4. python条件语句-Python3 条件控制
  5. ubuntu16.04 Nvidia 显卡的风扇调速及startx的后果
  6. server 2008R2 AD域环境中DHCP服务器的授权步骤
  7. SilkierQuartz 1.0.21 发布, 是一个 Quartz.NET 的强大且简单的Web管理工具和承载组件...
  8. java.lang.NoClassDefFoundError: org/apache/shiro/authc/AuthenticationToken
  9. 程序员面试金典 - 面试题 01.04. 回文排列(哈希map)
  10. 机器学习算法GBDT的面试总结
  11. 360浏览器登录_浏览器发展历史介绍及当今主流浏览器的详细对比
  12. android中的用户资源访问(一)
  13. java中的VO、PO、BO、DAO、POJO
  14. python将json转化为数组_将JSON转换为数组?
  15. 热敏电阻(NTC)的基本参数及其应用(图)
  16. Python——pyqt5的计算器(源码+打包)
  17. 第五章 数组Ivor Horton
  18. sim7600ce 拨号上网测试_SIM7600CE应用程序调试流程
  19. DataGridView控件数据导出表格
  20. adb连接夜神模拟器和连接夜神多开的方法

热门文章

  1. app被拒 Guideline 5.1.1 - Legal - Privacy - Data Collection and Storage
  2. 操作系统负责为方便用户管理计算机系统,操作系统负责为用户方便管理计算机系统的( )。...
  3. matlab加工表面微观,车铣复合加工表面微观几何形貌仿真及切削参数分析研究
  4. java第一阶段(day11)Utill包常用类
  5. 如何用C语言实现【猜拳游戏】
  6. 【支付宝小程序】显示 / 隐藏控件
  7. Segger J-Link 系列产品简介
  8. Matplotlib可视化预测双色球
  9. 神经网络预测彩票数据
  10. 自主设计的滑移转向机器人同步带传动stm32f103的can伺服电机控制