// // Created by 阳坤 on 2022/3/1. // #include #include #include #include #include #include "video_similarity.h" const int MAX_STACK_FRAMES = 128; void sig_crash(int sig) { printf("crash---->sig=%d \n",sig); FILE *fd; struct stat buf; const char * crash_path = "./video_similarity_comparison_crash.txt"; stat(crash_path, &buf); if (buf.st_size > 10 * 1000 * 1000) { // 超过10兆则清空内容 fd = fopen(crash_path, "w"); } else { fd = fopen(crash_path, "at"); } if (NULL == fd) { exit(0); } try { char szLine[512] = {0,}; time_t t = time(NULL); tm *now = localtime(&t); int nLen1 = sprintf(szLine, "#########################################################\n[%04d-%02d-%02d %02d:%02d:%02d][crash signal number:%d]\n", now->tm_year + 1900, now->tm_mon + 1, now->tm_mday, now->tm_hour, now->tm_min, now->tm_sec, sig); printf("crash---->%s \n",szLine); fwrite(szLine, 1, strlen(szLine), fd); #ifdef __linux void* array[MAX_STACK_FRAMES]; size_t size = 0; char** strings = NULL; size_t i, j; signal(sig, SIG_DFL); size = backtrace(array, MAX_STACK_FRAMES); strings = (char**)backtrace_symbols(array, size); //fprintf(stderr, "oncrash;\n"); for (i = 0; i < size; ++i) { char szLine[512] = {0, }; sprintf(szLine, "%d %s\n", i, strings[i]); fwrite(szLine, 1, strlen(szLine), fd); std::string symbol(strings[i]); size_t pos1 = symbol.find_first_of("["); size_t pos2 = symbol.find_last_of("]"); std::string address = symbol.substr(pos1 + 1, pos2 - pos1 -1); char cmd[128] = {0, }; sprintf(cmd, "addr2line -e video_similarity_comparison %s", address.c_str()); // test为应用程序名称,需要改为用户自己的应用程序名 FILE *fPipe = popen(cmd, "r"); if(fPipe != NULL){ char buff[1024]; memset(buff, 0, sizeof(buff)); char* ret = fgets(buff, sizeof(buff), fPipe); pclose(fPipe); fwrite(ret, 1, strlen(ret), fd); } } free(strings); #endif // __linux }catch (...) { // } signal(sig, SIG_DFL); fflush(fd); fclose(fd); fd = NULL; exit(0); } long video_similarity_detection_init(const char *url) { auto *ctx = (VideoSimilarityContext *) malloc(sizeof(VideoSimilarityContext)); if (!ctx)return -1; memset(ctx, 0, sizeof(VideoSimilarityContext)); ctx->video_path = strdup(url); return (long) ctx; } static const char *GetFileName(const char *ptr, int n) { int i = n; //这里i只是为循环即使终止了也未找到/而准备 ptr += n; //把指针移到字符串的尾部,即'\0'处 while (i-- > 0) { if ((*ptr--) == '/') //指针不断回移并判断是否为/符号 { break; //从后向前遇到第一个/后退出循环 } } ptr += 2; return ptr; //反回最后一个/后面的字符串即名称 } int video_similarity_detection_start(long id, int force_keyframe, DisableMediaType disableMediaType, std::vector *lists) { if (id <= 0)return -1; auto *ctx = (VideoSimilarityContext *) id; long d_id = initDecoder(ctx->video_path, force_keyframe, disableMediaType); ctx->decode_obj_id = d_id; if (ctx->decode_obj_id <= 0)return ctx->decode_obj_id; int exit = 0, ret = 0; av_read_decode_frame(ctx->decode_obj_id); auto *dctx = (DecoderContext *) ctx->decode_obj_id; dctx->vs_decodes = *lists; int index = 0; auto endTimeMs = (*lists)[index]->endTimeMs; while (!exit) { AVFrame *video_frame = NULL; dctx->video_queue->PopFront(video_frame); if (video_frame == NULL) { LOGE("read video frame end."); break; } int len = 0; if (ctx->log) fprintf(ctx->log, "fingerprintFromFFAVFrame 1\n"); const char *image_hash = fingerprintFromFFAVFrame(ctx->log, video_frame, &len); if (ctx->log) fprintf(ctx->log, "fingerprintFromFFAVFrame exit \n"); if (len > 64) { LOGE("size=%d \n", len); } auto *model = (ImageHashModel *) malloc(sizeof(ImageHashModel)); memset(model, 0, sizeof(ImageHashModel)); model->img_len = len; if (len > 0) { model->image_hash = static_cast(malloc(sizeof(char) * len)); memcpy((void *) model->image_hash, image_hash, len); } if (video_frame->pts >= endTimeMs && (*lists).size() > 1 && index + 1 < (*lists).size()) { index++; endTimeMs = (*lists)[index]->endTimeMs; } model->pts = video_frame->pts; // LOGE("push pts >>>>= %lld \n", model->pts); (*lists)[index]->hashs.push_back(model); if (ctx->log)fprintf(ctx->log, "image_hash \n"); if (image_hash) free((void *) image_hash); if (ctx->log) fprintf(ctx->log, "av_frame_free\n"); av_frame_free(&video_frame); if (ctx->log) fprintf(ctx->log, "av_frame_free 2\n"); } if (ctx->log) fprintf(ctx->log, "loop exit \n"); return 0; } int video_similarity_detection_close(long id) { if (id <= 0)return -1; auto *ctx = (VideoSimilarityContext *) id; if (ctx->video_path) { free((void *) ctx->video_path); ctx->video_path = NULL; } if (ctx->log) { fclose(ctx->log); ctx->log = NULL; } close_decoder(ctx->decode_obj_id); free(ctx); ctx = NULL; return 0; } VideoSimilarity *json2VideoSimilarity(const char *json) { VideoSimilarity *videoSimilarity; videoSimilarity = new VideoSimilarity(); Json::Reader reader; Json::Value value; if (reader.parse(json, value)) { Json::Value json_obj = value; if (json_obj.isMember("videoPath")) videoSimilarity->videoPath = strdup(json_obj["videoPath"].asString().c_str()); if (json_obj.isMember("clips") && json_obj["clips"].type() == Json::arrayValue) { for (int i = 0; i < json_obj["clips"].size(); ++i) { auto *videoSim = (VideoSimilarityModel *) malloc(sizeof(VideoSimilarityModel)); memset(videoSim, 0, sizeof(VideoSimilarityModel)); videoSim->startTimeMs = json_obj["clips"][i]["startTimeMs"].asInt(); videoSim->endTimeMs = json_obj["clips"][i]["endTimeMs"].asInt(); videoSimilarity->clips.push_back(videoSim); } } } return videoSimilarity; } const char *videoSimilarity2json(VideoSimilarity *videoSimilarity) { if (!videoSimilarity)return NULL; Json::Value obj; Json::Value array; Json::StreamWriterBuilder builder; if (videoSimilarity->videoPath) { obj["videoPath"] = videoSimilarity->videoPath; free((void *) videoSimilarity->videoPath); videoSimilarity->videoPath = NULL; } for (auto it = videoSimilarity->clips.begin(); it != videoSimilarity->clips.end();) { auto item = *it; Json::Value v; Json::Value v_array; v["startTimeMs"] = item->startTimeMs; v["endTimeMs"] = item->endTimeMs; for (auto it2 = item->hashs.begin(); it2 != item->hashs.end();) { ImageHashModel *item2 = *it2; Json::Value va; if (item->hashs.size() <= 1499) { // LOGE("size=%d %d\n", item->hashs.size(), item2->img_len); } if (item2->image_hash && item2->img_len > 0) { string append_array; for (int i = 0; i < item2->img_len; ++i) { char c = item2->image_hash[i]; if (c == 0) { append_array.append("0"); } else if (c == 1) { append_array.append("1"); } } va["imageHash"] = append_array.c_str(); free((void *) item2->image_hash); } va["hashSize"] = item2->img_len; va["pts"] = item2->pts; v_array.append(va); free(item2); item2 = NULL; it2 = item->hashs.erase(it2); } v["hashs"] = v_array; array.append(v); free(item); item = NULL; it = videoSimilarity->clips.erase(it); } obj["clips"] = array; const std::string json_file = Json::writeString(builder, obj); const char *ret_json = strdup(json_file.c_str()); videoSimilarity->clips.clear(); return ret_json; } /** * 获取视频相似值列表 * @param inputfile * @return */ const char *get_video_similarity_list(const char *inputjson) { signal(SIGABRT, sig_crash); signal(SIGSEGV, sig_crash); if (!inputjson)return NULL; // free((void*)inputjson); printf("get_video_similarity_list=%s \n", inputjson); auto *vs = json2VideoSimilarity(inputjson); long id = video_similarity_detection_init(vs->videoPath); const char *ret_json = NULL; if (id > 0) { if (!(((VideoSimilarityContext *) id)->log)) { int n = strlen(((VideoSimilarityContext *) id)->video_path); //计算字符串的长度(包括'\0') const char *name = GetFileName(((VideoSimilarityContext *) id)->video_path, n); //把字符串及其长度传给函数 printf("%s\n", name); //name就是那个名称,可以输出 char args[512]; sprintf(args, "/Users/devyk/Data/Project/sample/github_code/OpenCVSample/temp/%s.log", name); // sprintf(args, "/datalog/ffmpeg_opencv/%s.log", name); ((VideoSimilarityContext *) id)->log = fopen(args, "wb+"); printf("args===%s \n", args); if (((VideoSimilarityContext *) id)->log)fprintf(((VideoSimilarityContext *) id)->log, inputjson); } if (((VideoSimilarityContext *) id)->log) fprintf(((VideoSimilarityContext *) id)->log, "video_similarity_detection_start \n"); video_similarity_detection_start(id, 0, AUDIO, &vs->clips); if (((VideoSimilarityContext *) id)->log) fprintf(((VideoSimilarityContext *) id)->log, "video_similarity_detection_start exit \n"); video_similarity_detection_close(id); ret_json = videoSimilarity2json(vs); delete vs; vs = NULL; } return ret_json; }