--- /dev/null
+#include <stdio.h>\r
+#include "stdafx.h"\r
+#include "Help.h"\r
+#include "EditMain.h"\r
+#include "debug.h"\r
+\r
+\r
+void EditMain(T_EDIT_PARAM *prm){\r
+\r
+ GF_Err e;\r
+ T_MP4_INFO mi;\r
+ T_TS_LIST *ts = NULL;\r
+ T_TS_LIST *tsSort = NULL;\r
+\r
+ // \8f\89\8aú\89»\r
+ gf_sys_init();\r
+\r
+ ZeroMemory(&mi, sizeof(T_MP4_INFO));\r
+\r
+ // \83^\81[\83Q\83b\83g\83t\83@\83C\83\8b\82Ì\83I\81[\83v\83\93\r
+ mi.fp_in = gf_isom_open(prm->p_infile, GF_ISOM_OPEN_READ, NULL);\r
+ printf("\93ü\97Í\83t\83@\83C\83\8b... [%s]\n\n", prm->p_infile);\r
+\r
+ mi.i_trackCount = gf_isom_get_track_count(mi.fp_in);\r
+ \r
+ // \8ae\83g\83\89\83b\83N\82Ì\83t\83H\81[\83}\83b\83g\82ð\8eæ\93¾\r
+ u32 lst4CC[] = {GF_ISOM_BRAND_AVC1, GF_ISOM_BRAND_MP4V, GF_ISOM_BRAND_XVID};\r
+ SearchTrackOf4CC(&mi, lst4CC, 3);\r
+\r
+ // \96Ú\93I\82Ì\83g\83\89\83b\83N\82ª\8c©\82Â\82©\82ç\82È\82©\82Á\82½\8fê\8d\87\81B\r
+ if (mi.i_trackNo == NULL){\r
+ ErrorMessage(MSG_NO_4CC);\r
+ goto _ERROR_RET;\r
+ }\r
+\r
+ // \83T\83\93\83v\83\8b\90\94\82Ì\8eæ\93¾\r
+ mi.ui_sampleCount = gf_isom_get_sample_count(mi.fp_in, mi.i_trackNo);\r
+ if(mi.ui_sampleCount < 3){\r
+ ErrorMessage(MSG_NO_SAMPLE);\r
+ goto _ERROR_RET;\r
+ }\r
+\r
+ ts = new T_TS_LIST[mi.ui_sampleCount + 1];\r
+ ZeroMemory(ts, sizeof(T_TS_LIST) * mi.ui_sampleCount);\r
+\r
+ // \83T\83\93\83v\83\8b\8fî\95ñ\82ð\8eæ\93¾\82µ\81A\83f\83B\83\8c\83C\83t\83\8c\81[\83\80\94»\92è\81ECTS\8f\87\82É\95À\82Ñ\91Ö\82¦\r
+ printf("\83T\83\93\83v\83\8b\8fî\95ñ\8eæ\93¾\92\86...\n");\r
+ if(readTsFromFile(&mi, ts))\r
+ goto _ERROR_RET;\r
+\r
+ // \83s\83N\83`\83\83\95\\8e¦\8f\87\82Å\83\\81[\83g\r
+ tsSort = new T_TS_LIST[mi.ui_sampleCount + 1];\r
+ memcpy(tsSort, ts, sizeof(T_TS_LIST) * mi.ui_sampleCount);\r
+ qsort(tsSort, mi.ui_sampleCount, sizeof(T_TS_LIST), (int(*)(const void*, const void*))CompareTS_PTS);\r
+\r
+ // \8dÅ\8fI\83t\83\8c\81[\83\80\82ÌFPS\95â\8a®\r
+ u32 i = mi.ui_sampleCount;\r
+ tsSort[i].DTS = ts[i-1].DTS + (ts[i-1].DTS - ts[i-2].DTS);\r
+ tsSort[i].CTS_Offset = 0;\r
+ tsSort[i].CTS = tsSort[i-1].CTS + (tsSort[i-1].CTS - tsSort[i-2].CTS);\r
+ tsSort[i].PTS = tsSort[i-1].PTS + (tsSort[i-1].PTS - tsSort[i-2].PTS);\r
+ tsSort[i].samples = i+1;\r
+\r
+ // \83^\83C\83\80\83X\83P\81[\83\8b\82Ì\8eæ\93¾\r
+ mi.i_org_timescale = (int)gf_isom_get_media_timescale(mi.fp_in, mi.i_trackNo);\r
+\r
+ // \82±\82Ì\95Ó\82Å\83\82\81[\83h\95ª\8aò\r
+ if(prm->i_mode == MODE_IN){\r
+ // \83^\83C\83\80\83R\81[\83h\93ü\97Í\r
+\r
+ // \8dÅ\8f¬\83t\83\8c\81[\83\80\83\8c\81[\83g\8eæ\93¾\r
+ mi.i_org_timerate = getMinimumPTSDiff(&mi, tsSort);\r
+ if(prm->i_timerate <= 0) {\r
+ int rate = gcd(mi.i_org_timescale, mi.i_org_timerate);\r
+ prm->i_timerate = mi.i_org_timerate / rate;\r
+ }\r
+\r
+ // TimeCode V2 \82Ì\8eæ\82è\8d\9e\82Ý\r
+ if (prm->i_tcv == 1){\r
+ if(readTimeCodeFromFileV1(&mi, tsSort, prm))\r
+ goto _ERROR_RET;\r
+ } else if(prm->i_tcv == 2){\r
+ if(readTimeCodeFromFile(&mi, tsSort, prm))\r
+ goto _ERROR_RET;\r
+ } else {\r
+ goto _ERROR_RET;\r
+ }\r
+\r
+ // \92x\89\84\83t\83\8c\81[\83\80\90\94\8eæ\93¾\r
+ if(prm->i_delayFrame < 0) {\r
+ prm->i_delayFrame = getDelayFlame(&mi, ts);\r
+ }\r
+ mi.i_delayFrame = prm->i_delayFrame;\r
+ mi.i_initDelay = mi.i_delayFrame * (int)(getAveragePTSDiff(&mi, tsSort) / (double)prm->i_timerate + 0.5) * prm->i_timerate;\r
+\r
+ // \8c\8b\89Ê\82ð\83R\83s\81[\82µ\82Ä\83s\83N\83`\83\83\8f\87\82É\83\\81[\83g\r
+ memcpy(ts, tsSort, sizeof(T_TS_LIST) * mi.ui_sampleCount);\r
+ qsort(ts, mi.ui_sampleCount, sizeof(T_TS_LIST), (int(*)(const void*, const void*))CompareTS_Sample);\r
+\r
+\r
+ // \8fî\95ñ\82Ì\95\\8e¦\r
+ printf("\n");\r
+ printf("--- input ---\n");\r
+ printf("TimeScale \81F%d\n", mi.i_org_timescale);\r
+ printf("TimeRate \81F%d\n", mi.i_org_timerate);\r
+ printf("Sample Count \81F%d\n", mi.ui_sampleCount);\r
+ printf("Delay Frame \81F%d\n", mi.i_delayFrame);\r
+ printf("Delay Time \81F%d\n", mi.i_initDelay);\r
+ printf("\n");\r
+ printf("--- output ---\n");\r
+ printf("TimeScale \81F%d\n", prm->i_timescale);\r
+ printf("TimeRate \81F%d\n", prm->i_timerate);\r
+ printf("Multiple \81F%lf\n", prm->f_scaleFct);\r
+ printf("\n");\r
+ printf("\83t\83@\83C\83\8b\8fo\97Í\92\86... [%s]\n", prm->p_outfile);\r
+\r
+ u32 readDscIdx = 0;\r
+ u32 destTrack = 0;\r
+ mi.fp_out = gf_isom_open(prm->p_outfile, GF_ISOM_OPEN_WRITE, NULL);\r
+\r
+\r
+ // \8fo\97Í\8aJ\8en\r
+ for (int trackIdx=1; trackIdx<=mi.i_trackCount; trackIdx++){\r
+ // \83g\83\89\83b\83N\82Ì\83R\83s\81[\r
+ gf_isom_clone_track(mi.fp_in, trackIdx, mi.fp_out, true, &destTrack);\r
+ // edts\82Ì\8dí\8f\9c\r
+ gf_isom_remove_edit_segments(mi.fp_out, destTrack);\r
+\r
+ if (trackIdx != mi.i_trackNo){\r
+ u32 sampleCount = gf_isom_get_sample_count(mi.fp_in, trackIdx);\r
+ for(u32 i=1; i<=sampleCount; i++){\r
+ printf("... %5.1f%%\r", (double)i/(double)sampleCount * 100.0);\r
+ GF_ISOSample *sample = gf_isom_get_sample(mi.fp_in, trackIdx, i, &readDscIdx);\r
+ e = gf_isom_add_sample(mi.fp_out, destTrack, readDscIdx, sample);\r
+ gf_isom_sample_del(&sample);\r
+ }\r
+\r
+ } else {\r
+ // \83^\83C\83\80\83X\83P\81[\83\8b\90Ý\92è\r
+ e = gf_isom_set_media_timescale(mi.fp_out, destTrack, (u32)prm->i_timescale);\r
+ if(e)\r
+ printf("!!! \83^\83C\83\80\83X\83P\81[\83\8b\90Ý\92è\8e¸\94s : %d !!!\n", e);\r
+\r
+ // DTS\82ð\90Ý\92è\82µ\8fo\97Í\r
+ s64 before_dts = -1;\r
+ int delta_time = int((prm->i_timerate * prm->f_scaleFct) / (mi.i_delayFrame*2));\r
+\r
+ if(delta_time < 1 && prm->b_dc){\r
+ ErrorMessage(MSG_MORE_SMALL_TIMERATE);\r
+ break;\r
+ }\r
+\r
+ for(u32 i=0; i<mi.ui_sampleCount; i++){\r
+ printf("... %5.1f%%\r", (double)i/(double)mi.ui_sampleCount * 100.0);\r
+\r
+ s64 cts = 0;\r
+ s64 dts = 0;\r
+ int offset = 0;\r
+ int dts_delay = 0;\r
+ int cts_delay = 0;\r
+ int ts_diff = 0;\r
+\r
+ cts = ts[i].PTS;\r
+ if(!prm->b_dc){\r
+ dts_delay = 0;\r
+ cts_delay = mi.i_initDelay;\r
+ } else {\r
+ for(u32 k=MAX(0, i - mi.i_delayFrame); k<i; k++)\r
+ ts_diff += (int)(tsSort[k + 1].PTS - tsSort[k].PTS);\r
+\r
+ dts_delay = MAX(mi.i_initDelay, ts_diff);\r
+ cts_delay = 0;\r
+ }\r
+\r
+ if(dts_delay < tsSort[i].PTS)\r
+ dts = tsSort[i].PTS - dts_delay;\r
+\r
+ // \91O\89ñ\82ÌDTS\82æ\82è\82à\92l\82Í\91å\82«\82\82È\82¯\82ê\82Î\82È\82ç\82È\82¢\81B\r
+ if(dts <= before_dts)\r
+ dts = before_dts + delta_time;\r
+\r
+ // CTS_Offset\82Ì\8eZ\8fo\r
+ offset = (int)(cts - dts + cts_delay);\r
+\r
+ // \83I\83t\83Z\83b\83g\82Ì\8cv\8eZ\82Å\95\89\82É\82È\82Á\82Ä\82µ\82Ü\82Á\82½\8fê\8d\87\r
+ if (offset < 0){\r
+ dts += offset;\r
+ offset = 0;\r
+ }\r
+\r
+ ts[i].DTS = before_dts = dts;\r
+ ts[i].CTS_Offset = offset;\r
+\r
+ // \83`\83F\83b\83N\r
+ if( (dts + (s64)offset - (s64)ts[0].CTS_Offset) != cts )\r
+ printf("!!! \95\\8e¦\83^\83C\83~\83\93\83O\83G\83\89\81[ / Track:%d Frame:%d Target PTS:%I64d (DTS:%I64d, CTS_Offset:%d, Delay:%d) !!!\n", destTrack, i+1, cts, dts, offset, ts[0].CTS_Offset);\r
+\r
+ GF_ISOSample *sample = gf_isom_get_sample(mi.fp_in, mi.i_trackNo, i+1, &readDscIdx);\r
+ sample->DTS = ts[i].DTS;\r
+ sample->CTS_Offset = ts[i].CTS_Offset;\r
+ e = gf_isom_add_sample(mi.fp_out, destTrack, readDscIdx, sample);\r
+\r
+ if(e)\r
+ printf("!!! \83T\83\93\83v\83\8b\8f\91\82«\8d\9e\82Ý\83G\83\89\81[ / Track:%d Frame:%d DTS:%I64d, CTS_Offset:%d Err:%d !!!\n", destTrack, i+1, sample->DTS, sample->CTS_Offset, e);\r
+ gf_isom_sample_del(&sample);\r
+ }\r
+\r
+ // edts\82Ì\91}\93ü\r
+ //GF_ISOSample *sample = gf_isom_get_sample_info(mi.fp_out, destTrack, 1, NULL, NULL);\r
+ //if(sample->CTS_Offset > 0){\r
+ // u64 trackDur = gf_isom_get_track_duration(mi.fp_out, destTrack);\r
+ // gf_isom_remove_edit_segments(mi.fp_out, destTrack);\r
+ // gf_isom_append_edit_segment(mi.fp_out, destTrack, trackDur, sample->CTS_Offset, GF_ISOM_EDIT_NORMAL);\r
+ //}\r
+ //gf_isom_sample_del(&sample);\r
+ }\r
+\r
+ printf("... %d\83g\83\89\83b\83N\8fo\97Í\8fI\97¹\n", trackIdx);\r
+ }\r
+\r
+ // \8fo\97Í\83t\83@\83C\83\8b\82ð\95Â\82¶\82é\r
+ gf_isom_clone_pl_indications(mi.fp_in, mi.fp_out);\r
+ gf_isom_clone_root_od(mi.fp_in, mi.fp_out);\r
+\r
+ u64 duration = gf_isom_get_duration(mi.fp_out);\r
+ gf_isom_make_interleave(mi.fp_out, 0.5);\r
+ gf_isom_close(mi.fp_out);\r
+\r
+ }\r
+ else if (prm->i_mode == MODE_OUT){\r
+ // TIMECODE\82Ì\8fo\97Í\r
+ if(prm->i_tcv == 2){\r
+ FILE *fpout;\r
+ if((fpout = fopen(prm->p_outfile, "wb")) != NULL){\r
+ fprintf(fpout, "# timecode format v2\r\n");\r
+ for(u32 i=0; i<mi.ui_sampleCount; i++){\r
+ fprintf(fpout, "%.6lf\r\n", (double)tsSort[i].PTS / (double)mi.i_org_timescale * 1000.0);\r
+ }\r
+ }\r
+ fclose(fpout);\r
+ printf("... timecode format v2 \8fo\97Í\8fI\97¹\n");\r
+ }\r
+ else if(prm->i_tcv == 1){\r
+ FILE *fpout;\r
+ if((fpout = fopen(prm->p_outfile, "wb")) != NULL){\r
+ fprintf(fpout, "# timecode format v1\r\n");\r
+ fprintf(fpout, "Assume %.6lf\r\n", getMaximumFps(&mi, tsSort));\r
+ u32 stpos = 0;\r
+ double fps = 0.0;\r
+ double beforFps = (double)mi.i_org_timescale/(double)(tsSort[1].PTS - tsSort[0].PTS);\r
+ for(u32 i=0; i<mi.ui_sampleCount; i++){\r
+ fps = (double)mi.i_org_timescale/(double)(tsSort[i+1].PTS - tsSort[i].PTS);\r
+ if (fps != beforFps){\r
+ fprintf(fpout, "%d,%d,%.6lf\r\n",stpos, i-1, beforFps);\r
+ beforFps = fps;\r
+ stpos = i;\r
+ }\r
+ }\r
+ if(stpos <= mi.ui_sampleCount - 1){\r
+ fprintf(fpout, "%d,%d,%.6lf\r\n",stpos, mi.ui_sampleCount - 1, fps);\r
+ }\r
+ }\r
+ fclose(fpout);\r
+ printf("... timecode format v1 \8fo\97Í\8fI\97¹\n");\r
+ } else {\r
+ goto _ERROR_RET;\r
+ }\r
+ }\r
+\r
+\r
+_ERROR_RET:\r
+\r
+ // \83t\83@\83C\83\8b\82ð\95Â\82¶\82Ä\8fI\97¹\r
+ gf_isom_close(mi.fp_in);\r
+\r
+ if(ts) delete [] ts;\r
+ if(tsSort) delete [] tsSort;\r
+ // \8dÅ\8fI\r
+ gf_sys_close();\r
+}\r
+\r