bool CMovieCut::truncateMovie(MI_MOVIE_INFO * minfo) { off64_t secsize = getSecondSize(minfo); if (minfo->bookmarks.end == 0 || secsize == 0) return false; off64_t newsize = secsize * minfo->bookmarks.end; printf("CMovieCut::%s: [%s] truncate to %d sec, new size %" PRId64 "\n", __func__, minfo->file.Name.c_str(), minfo->bookmarks.end, newsize); if (truncate(minfo->file.Name.c_str(), newsize)) { perror(minfo->file.Name.c_str()); return false; } minfo->file.Size = newsize; minfo->length = minfo->bookmarks.end/60; minfo->bookmarks.end = 0; reset_atime(minfo->file.Name.c_str(), minfo->file.Time); CMovieInfo cmovie; cmovie.saveMovieInfo(*minfo); WriteHeader(minfo->file.Name.c_str(), newsize/secsize*1000); return true; }
bool CMovieCut::copyMovie(MI_MOVIE_INFO * minfo, bool onefile) { struct mybook books[MI_MOVIE_BOOK_USER_MAX+2]; struct stat64 s; char dpart[255]; unsigned char psi[PSI_SIZE]; int dstfd = -1, srcfd = -1; off64_t spos = 0, btotal = 0; time_t tt = time(0); bool need_gop = 0; bool dst_done = 0; bool was_cancel = false; bool retval = false; int bcount = 0; off64_t newsize = 0; off64_t secsize = getSecondSize(minfo); for (int book_nr = 0; book_nr < MI_MOVIE_BOOK_USER_MAX; book_nr++) { if (minfo->bookmarks.user[book_nr].pos != 0 && minfo->bookmarks.user[book_nr].length > 0) { books[bcount].pos = (minfo->bookmarks.user[book_nr].pos * secsize)/188 * 188; if (books[bcount].pos > SAFE_GOP) books[bcount].pos -= SAFE_GOP; books[bcount].len = (minfo->bookmarks.user[book_nr].length * secsize)/188 * 188; books[bcount].ok = 1; printf("copy: jump bookmark %d at %" PRId64 " len %" PRId64 "\n", bcount, books[bcount].pos, books[bcount].len); newsize += books[bcount].len; bcount++; } } if (!bcount) return false; unsigned char * buf = new unsigned char[BUF_SIZE]; if (buf == 0) { perror("new"); return false; } paintProgress(true); printf("********* %d boormarks, to %s file(s), expected size to copy %" PRId64 ", start time %s", bcount, onefile ? "one" : "many", newsize, ctime(&tt)); if (read_psi(minfo->file.Name.c_str(), &psi[0])) { perror(minfo->file.Name.c_str()); goto ret_err; } srcfd = open(minfo->file.Name.c_str(), O_RDONLY | O_LARGEFILE); if (srcfd < 0) { perror(minfo->file.Name.c_str()); goto ret_err; } stat64(minfo->file.Name.c_str(), &s); for (int i = 0; i < bcount; i++) { printf("\ncopy: processing bookmark %d at %" PRId64 " len %" PRId64 "\n", i, books[i].pos, books[i].len); if (!dst_done || !onefile) { findNewName(minfo->file.Name.c_str(), dpart, sizeof(dpart)); dstfd = open(dpart, O_CREAT|O_WRONLY|O_TRUNC| O_LARGEFILE, 0644); printf("copy: new file %s fd %d\n", dpart, dstfd); if (dstfd < 0) { printf("failed to open %s\n", dpart); goto ret_err; } dst_done = 1; spos = 0; write(dstfd, psi, PSI_SIZE); } need_gop = 1; off64_t offset = books[i].pos; lseek64(srcfd, offset, SEEK_SET); off64_t until = books[i].pos + books[i].len; printf("copy: read from %" PRId64 " to %" PRId64 " read size %d want gop %d\n", offset, until, BUF_SIZE, need_gop); while (offset < until) { size_t toread = (until-offset) > BUF_SIZE ? BUF_SIZE : until - offset; int msg = getInput(); was_cancel = msg & 2; if (msg & 4) { unlink(dpart); retval = true; goto ret_err; } size_t r = read(srcfd, buf, toread); if (r > 0) { int wptr = 0; if (r != toread) printf("****** short read ? %d\n", (int)r); if (buf[0] != 0x47) printf("copy: buffer not aligned at %" PRId64 "\n", offset); if (need_gop) { int gop = find_gop(buf, r); if (gop >= 0) { printf("cut: GOP found at %" PRId64 " offset %d\n", (off64_t)(offset+gop), gop); newsize -= gop; wptr = gop; } else printf("cut: GOP needed, but not found\n"); need_gop = 0; } offset += r; spos += r - wptr; btotal += r; percent = (int) ((float)(btotal)/(float)(newsize)*100.); paintProgress(msg != 0); size_t wr = write(dstfd, &buf[wptr], r-wptr); if (wr < (r-wptr)) { printf("write to %s failed\n", dpart); unlink(dpart); goto ret_err; } } else if (offset < s.st_size) { /* read error ? */ perror(minfo->file.Name.c_str()); break; } } /* while(offset < until) */ if (!onefile) { close(dstfd); dstfd = -1; save_info(minfo, dpart, spos, secsize); time_t tt1 = time(0); printf("copy: ********* %s: total written %" PRId64 " took %ld secs\n", dpart, spos, tt1-tt); } } /* for all books */ if (onefile) { save_info(minfo, dpart, spos, secsize); time_t tt1 = time(0); printf("copy: ********* %s: total written %" PRId64 " took %ld secs\n", dpart, spos, tt1-tt); } retval = true; ret_err: if (srcfd >= 0) close(srcfd); if (dstfd >= 0) close(dstfd); delete [] buf; if (was_cancel) g_RCInput->postMsg(CRCInput::RC_home, 0); frameBuffer->paintBoxRel(x + 40, y+12, 200, 15, COL_INFOBAR_PLUS_0);//TODO: remove unneeded box paints return retval; }
bool CMovieCut::cutMovie(MI_MOVIE_INFO * minfo) { struct mybook books[MI_MOVIE_BOOK_USER_MAX+2]; unsigned char psi[PSI_SIZE]; char dpart[255]; int bcount = 0; int dstfd = -1, srcfd = -1; struct stat64 s; off64_t spos = 0; bool need_gop = 0; int was_cancel = 0; bool retval = false; time_t tt = time(0); time_t tt1; off64_t size = minfo->file.Size; off64_t secsize = getSecondSize(minfo); off64_t newsize = size; if (minfo->bookmarks.start != 0) { books[bcount].pos = 0; books[bcount].len = (minfo->bookmarks.start * secsize)/188 * 188; if (books[bcount].len > SAFE_GOP) books[bcount].len -= SAFE_GOP; books[bcount].ok = 1; printf("CMovieCut::%s: start bookmark %d at %" PRId64 " len %" PRId64 "\n", __func__, bcount, books[bcount].pos, books[bcount].len); bcount++; } for (int book_nr = 0; book_nr < MI_MOVIE_BOOK_USER_MAX; book_nr++) { if (minfo->bookmarks.user[book_nr].pos != 0 && minfo->bookmarks.user[book_nr].length > 0) { books[bcount].pos = (minfo->bookmarks.user[book_nr].pos * secsize)/188 * 188; books[bcount].len = (minfo->bookmarks.user[book_nr].length * secsize)/188 * 188; if (books[bcount].len > SAFE_GOP) books[bcount].len -= SAFE_GOP; books[bcount].ok = 1; printf("CMovieCut::%s: jump bookmark %d at %" PRId64 " len %" PRId64 " -> skip to %" PRId64 "\n", __func__, bcount, books[bcount].pos, books[bcount].len, books[bcount].pos+books[bcount].len); bcount++; } } if (minfo->bookmarks.end != 0) { books[bcount].pos = ((off64_t) minfo->bookmarks.end * secsize)/188 * 188; books[bcount].len = size - books[bcount].pos; books[bcount].ok = 1; printf("CMovieCut::%s: end bookmark %d at %" PRId64 "\n", __func__, bcount, books[bcount].pos); bcount++; } if (!bcount) return false; unsigned char * buf = new unsigned char[BUF_SIZE]; if (buf == 0) { perror("new"); return false; } paintProgress(true); qsort(books, bcount, sizeof(struct mybook), compare_book); for (int i = 0; i < bcount; i++) { if (books[i].ok) { //printf("cut: bookmark %d at %" PRId64 " len %" PRId64 " -> skip to %" PRId64 "\n", i, books[i].pos, books[i].len, books[i].pos+books[i].len); newsize -= books[i].len; off64_t curend = books[i].pos + books[i].len; /* check for overlapping bookmarks */ for (int j = i + 1; j < bcount; j++) { if ((books[j].pos > books[i].pos) && (books[j].pos < curend)) { off64_t newend = books[j].pos + books[j].len; if (newend > curend) { printf("CMovieCut::%s: bad bookmark %d, position %" PRId64 " len %" PRId64 ", adjusting..\n", __func__, j, books[j].pos, books[j].len); books[j].pos = curend; books[j].len = newend - curend; } else { printf("CMovieCut::%s: bad bookmark %d, position %" PRId64 " len %" PRId64 ", skipping..\n", __func__, j, books[j].pos, books[j].len); books[j].ok = 0; } } } } } findNewName(minfo->file.Name.c_str(), dpart, sizeof(dpart)); int bindex = 0; off64_t bpos = books[bindex].pos; off64_t bskip = books[bindex].len; off64_t offset = 0; printf("CMovieCut::%s: new file %s, expected size %" PRId64 ", start time %s", __func__, dpart, newsize, ctime(&tt)); dstfd = open(dpart, O_CREAT|O_WRONLY|O_TRUNC| O_LARGEFILE, 0644); if (dstfd < 0) { perror(dpart); goto ret_err; } if (read_psi(minfo->file.Name.c_str(), &psi[0])) { perror(minfo->file.Name.c_str()); goto ret_err; } write(dstfd, psi, PSI_SIZE); stat64(minfo->file.Name.c_str(), &s); srcfd = open(minfo->file.Name.c_str(), O_RDONLY | O_LARGEFILE); if (srcfd < 0) { perror(minfo->file.Name.c_str()); goto ret_err; } lseek64(srcfd, offset, SEEK_SET); /* process all bookmarks */ while (true) { off64_t until = bpos; printf("CMovieCut::%s: bookmark #%d reading from %" PRId64 " to %" PRId64 " (%" PRId64 ") want gop %d\n", __func__, bindex, offset, until, until - offset, need_gop); /* read up to jump end */ while (offset < until) { int msg = getInput(); was_cancel = msg & 2; if (msg & 4) { unlink(dpart); retval = true; goto ret_err; } size_t toread = (until-offset) > BUF_SIZE ? BUF_SIZE : until - offset; size_t r = read(srcfd, buf, toread); if (r > 0) { int wptr = 0; if (r != toread) printf("CMovieCut::%s: short read at %" PRId64 ": %d\n", __func__, offset, (int)r); if (buf[0] != 0x47) printf("CMovieCut::%s: buffer not aligned at %" PRId64 "\n", __func__, offset); if (need_gop) { int gop = find_gop(buf, r); if (gop >= 0) { printf("CMovieCut::%s: GOP found at %" PRId64 " offset %d\n", __func__, (off64_t)(offset+gop), gop); newsize -= gop; wptr = gop; } else printf("CMovieCut::%s: GOP not found\n", __func__); need_gop = 0; } offset += r; spos += r - wptr; percent = (int) ((float)(spos)/(float)(newsize)*100.); paintProgress(msg != 0); size_t wr = write(dstfd, &buf[wptr], r-wptr); if (wr < (r-wptr)) { perror(dpart); goto ret_err; } } else if (offset < s.st_size) { /* read error ? */ perror(minfo->file.Name.c_str()); goto ret_err; } } printf("CMovieCut::%s: current file pos %" PRId64 " write pos %" PRId64 " book pos %" PRId64 " next offset %" PRId64 "\n", __func__, offset, spos, bpos, bpos + bskip); need_gop = 1; offset = bpos + bskip; bindex++; while(bindex < bcount) { if(books[bindex].ok) break; else bindex++; } if(bindex < bcount) { bpos = books[bindex].pos; bskip = books[bindex].len; } else bpos = size; if (offset >= s.st_size) { printf("CMovieCut::%s: offset behind EOF: %" PRId64 " from %" PRId64 "\n", __func__, offset, s.st_size); break; } lseek64(srcfd, offset, SEEK_SET); } tt1 = time(0); printf("CMovieCut::%s: total written %" PRId64 " tooks %ld secs end time %s", __func__, spos, tt1-tt, ctime(&tt1)); save_info(minfo, dpart, spos, secsize); retval = true; ret_err: if (srcfd >= 0) close(srcfd); if (dstfd >= 0) close(dstfd); delete [] buf; if (was_cancel) g_RCInput->postMsg(CRCInput::RC_home, 0); frameBuffer->paintBoxRel(x + 40, y+12, 200, 15, COL_INFOBAR_PLUS_0);//TODO: remove unneeded box paints return retval; }
void InputMatrix::calculate(IrredundantMatrix &irredundantMatrix) { Divide2Plan planBuilder(_r2Counts.data(), _r2Counts.size()); std::vector<std::thread> threads(planBuilder.getMaxThreadsCount()); std::mutex sync; std::condition_variable mcv; std::condition_variable wcv; int unblockedStep = -1; int waited = planBuilder.getMaxThreadsCount(); for(auto threadId = 0; threadId < planBuilder.getMaxThreadsCount(); ++threadId) { START_COLLECT_TIME(threading, Counters::Threading); threads[threadId] = std::thread([this, threadId, &irredundantMatrix, &planBuilder, &sync, &mcv, &wcv, &unblockedStep, &waited]() { TimeCollector::ThreadInitialize(); for(auto step = 0; step < planBuilder.getStepsCount(); ++step) { DEBUG_INFO("Worker " << threadId << ", step: " << step << ", waiting"); { std::unique_lock<std::mutex> locker(sync); wcv.wait(locker, [step, &unblockedStep]{ return unblockedStep >= step; }); } DEBUG_INFO("Worker " << threadId << ", step: " << step << ", started"); if (threadId < planBuilder.getThreadsCountForStep(step)) { #ifdef DIFFERENT_MATRICES IrredundantMatrix matrixForThread(_qColsCount); auto currentMatrix = &matrixForThread; #else auto currentMatrix = &irredundantMatrix; #endif auto task = planBuilder.getTask(step, threadId); if (!task->isEmpty()) { DEBUG_INFO("Thread " << threadId << " is working on " << task->getFirstSize() << ":" << task->getSecondSize()); for(auto i=0; i<task->getFirstSize(); ++i) { for(auto j=0; j<task->getSecondSize(); ++j) { processBlock(*currentMatrix, _r2Indexes[task->getFirst(i)], _r2Counts[task->getFirst(i)], _r2Indexes[task->getSecond(j)], _r2Counts[task->getSecond(j)]); } } #ifdef DIFFERENT_MATRICES irredundantMatrix.addMatrixConcurrent(std::move(matrixForThread)); #endif } } { std::unique_lock<std::mutex> locker(sync); waited -= 1; locker.unlock(); mcv.notify_one(); } DEBUG_INFO("Worker " << threadId << ", step: " << step << ", finished"); } DEBUG_INFO("Worker " << threadId << " finished"); TimeCollector::ThreadFinalize(); }); STOP_COLLECT_TIME(threading); } for(auto step = 0; step < planBuilder.getStepsCount(); ++step) { DEBUG_INFO("Master, step: " << step << ", starting"); { std::unique_lock<std::mutex> locker(sync); waited = planBuilder.getMaxThreadsCount(); unblockedStep = step; sync.unlock(); wcv.notify_all(); } DEBUG_INFO("Master, step: " << step << ", started"); { std::unique_lock<std::mutex> locker(sync); mcv.wait(locker, [&waited]{ return waited == 0; }); } DEBUG_INFO("Master, step: " << step << ", finished"); } for(auto threadId = 0; threadId < planBuilder.getMaxThreadsCount(); ++threadId) { threads[threadId].join(); } }