123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306 |
- //
- // Created by 阳坤 on 2022/3/1.
- //
- #include <json/reader.h>
- #include <json/writer.h>
- #include <sys/stat.h>
- #include <signal.h>
- #include <execinfo.h>
- #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<VideoSimilarityModel *> *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<const char *>(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;
- }
|