123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218 |
- //
- // Created by 阳坤 on 2022/3/1.
- //
- #include <json/reader.h>
- #include <json/writer.h>
- #include "video_similarity.h"
- 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;
- const char *image_hash = fingerprintFromFFAVFrame(ctx->log, video_frame, &len);
- 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);
- fprintf(ctx->log, "image_hash ");
- if (image_hash)
- free((void *) image_hash);
- fprintf(ctx->log, "image_hash 2");
- av_frame_free(&video_frame);
- }
- 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) {
- if (!inputjson)return NULL;
- 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","test");
- sprintf(args, "/datalog/%s.log", "test");
- ((VideoSimilarityContext *) id)->log = fopen(args, "wb+");
- printf("args===%s \n", args);
- fprintf(((VideoSimilarityContext *) id)->log, inputjson);
- }
- video_similarity_detection_start(id, 0, AUDIO,
- &vs->clips);
- video_similarity_detection_close(id);
- ret_json = videoSimilarity2json(vs);
- delete vs;
- vs = NULL;
- }
- return ret_json;
- }
|