4 #include "EditMain.h"
\r
8 void EditMain(T_EDIT_PARAM *prm){
\r
12 T_TS_LIST *ts = NULL;
\r
13 T_TS_LIST *tsSort = NULL;
\r
18 ZeroMemory(&mi, sizeof(T_MP4_INFO));
\r
20 //
\83^
\81[
\83Q
\83b
\83g
\83t
\83@
\83C
\83\8b\82Ì
\83I
\81[
\83v
\83\93\r
21 mi.fp_in = gf_isom_open(prm->p_infile, GF_ISOM_OPEN_READ, NULL);
\r
22 printf("
\93ü
\97Í
\83t
\83@
\83C
\83\8b... [%s]\n\n", prm->p_infile);
\r
24 mi.i_trackCount = gf_isom_get_track_count(mi.fp_in);
\r
26 //
\8ae
\83g
\83\89\83b
\83N
\82Ì
\83t
\83H
\81[
\83}
\83b
\83g
\82ð
\8eæ
\93¾
\r
27 u32 lst4CC[] = {GF_ISOM_BRAND_AVC1, GF_ISOM_BRAND_MP4V, GF_ISOM_BRAND_XVID};
\r
28 SearchTrackOf4CC(&mi, lst4CC, 3);
\r
30 //
\96Ú
\93I
\82Ì
\83g
\83\89\83b
\83N
\82ª
\8c©
\82Â
\82©
\82ç
\82È
\82©
\82Á
\82½
\8fê
\8d\87\81B
\r
31 if (mi.i_trackNo == NULL){
\r
32 ErrorMessage(MSG_NO_4CC);
\r
36 //
\83T
\83\93\83v
\83\8b\90\94\82Ì
\8eæ
\93¾
\r
37 mi.ui_sampleCount = gf_isom_get_sample_count(mi.fp_in, mi.i_trackNo);
\r
38 if(mi.ui_sampleCount < 3){
\r
39 ErrorMessage(MSG_NO_SAMPLE);
\r
43 ts = new T_TS_LIST[mi.ui_sampleCount + 1];
\r
44 ZeroMemory(ts, sizeof(T_TS_LIST) * mi.ui_sampleCount);
\r
46 //
\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
47 printf("
\83T
\83\93\83v
\83\8b\8fî
\95ñ
\8eæ
\93¾
\92\86...\n");
\r
48 if(readTsFromFile(&mi, ts))
\r
51 //
\83s
\83N
\83`
\83\83\95\
\8e¦
\8f\87\82Å
\83\
\81[
\83g
\r
52 tsSort = new T_TS_LIST[mi.ui_sampleCount + 1];
\r
53 memcpy(tsSort, ts, sizeof(T_TS_LIST) * mi.ui_sampleCount);
\r
54 qsort(tsSort, mi.ui_sampleCount, sizeof(T_TS_LIST), (int(*)(const void*, const void*))CompareTS_PTS);
\r
56 //
\8dÅ
\8fI
\83t
\83\8c\81[
\83\80\82ÌFPS
\95â
\8a®
\r
57 u32 i = mi.ui_sampleCount;
\r
58 tsSort[i].DTS = ts[i-1].DTS + (ts[i-1].DTS - ts[i-2].DTS);
\r
59 tsSort[i].CTS_Offset = 0;
\r
60 tsSort[i].CTS = tsSort[i-1].CTS + (tsSort[i-1].CTS - tsSort[i-2].CTS);
\r
61 tsSort[i].PTS = tsSort[i-1].PTS + (tsSort[i-1].PTS - tsSort[i-2].PTS);
\r
62 tsSort[i].samples = i+1;
\r
64 //
\83^
\83C
\83\80\83X
\83P
\81[
\83\8b\82Ì
\8eæ
\93¾
\r
65 mi.i_org_timescale = (int)gf_isom_get_media_timescale(mi.fp_in, mi.i_trackNo);
\r
67 //
\82±
\82Ì
\95Ó
\82Å
\83\82\81[
\83h
\95ª
\8aò
\r
68 if(prm->i_mode == MODE_IN){
\r
69 //
\83^
\83C
\83\80\83R
\81[
\83h
\93ü
\97Í
\r
71 //
\8dÅ
\8f¬
\83t
\83\8c\81[
\83\80\83\8c\81[
\83g
\8eæ
\93¾
\r
72 mi.i_org_timerate = getMinimumPTSDiff(&mi, tsSort);
\r
73 if(prm->i_timerate <= 0) {
\r
74 int rate = gcd(mi.i_org_timescale, mi.i_org_timerate);
\r
75 prm->i_timerate = mi.i_org_timerate / rate;
\r
78 // TimeCode V2
\82Ì
\8eæ
\82è
\8d\9e\82Ý
\r
79 if (prm->i_tcv == 1){
\r
80 if(readTimeCodeFromFileV1(&mi, tsSort, prm))
\r
82 } else if(prm->i_tcv == 2){
\r
83 if(readTimeCodeFromFile(&mi, tsSort, prm))
\r
89 //
\92x
\89\84\83t
\83\8c\81[
\83\80\90\94\8eæ
\93¾
\r
90 if(prm->i_delayFrame < 0) {
\r
91 prm->i_delayFrame = getDelayFlame(&mi, ts);
\r
93 mi.i_delayFrame = prm->i_delayFrame;
\r
94 mi.i_initDelay = mi.i_delayFrame * (int)(getAveragePTSDiff(&mi, tsSort) / (double)prm->i_timerate + 0.5) * prm->i_timerate;
\r
96 //
\8c\8b\89Ê
\82ð
\83R
\83s
\81[
\82µ
\82Ä
\83s
\83N
\83`
\83\83\8f\87\82É
\83\
\81[
\83g
\r
97 memcpy(ts, tsSort, sizeof(T_TS_LIST) * mi.ui_sampleCount);
\r
98 qsort(ts, mi.ui_sampleCount, sizeof(T_TS_LIST), (int(*)(const void*, const void*))CompareTS_Sample);
\r
101 //
\8fî
\95ñ
\82Ì
\95\
\8e¦
\r
103 printf("--- input ---\n");
\r
104 printf("TimeScale
\81F%d\n", mi.i_org_timescale);
\r
105 printf("TimeRate
\81F%d\n", mi.i_org_timerate);
\r
106 printf("Sample Count
\81F%d\n", mi.ui_sampleCount);
\r
107 printf("Delay Frame
\81F%d\n", mi.i_delayFrame);
\r
108 printf("Delay Time
\81F%d\n", mi.i_initDelay);
\r
110 printf("--- output ---\n");
\r
111 printf("TimeScale
\81F%d\n", prm->i_timescale);
\r
112 printf("TimeRate
\81F%d\n", prm->i_timerate);
\r
113 printf("Multiple
\81F%lf\n", prm->f_scaleFct);
\r
115 printf("
\83t
\83@
\83C
\83\8b\8fo
\97Í
\92\86... [%s]\n", prm->p_outfile);
\r
117 u32 readDscIdx = 0;
\r
119 mi.fp_out = gf_isom_open(prm->p_outfile, GF_ISOM_OPEN_WRITE, NULL);
\r
122 //
\8fo
\97Í
\8aJ
\8en
\r
123 for (int trackIdx=1; trackIdx<=mi.i_trackCount; trackIdx++){
\r
124 //
\83g
\83\89\83b
\83N
\82Ì
\83R
\83s
\81[
\r
125 gf_isom_clone_track(mi.fp_in, trackIdx, mi.fp_out, true, &destTrack);
\r
126 // edts
\82Ì
\8dí
\8f\9c\r
127 gf_isom_remove_edit_segments(mi.fp_out, destTrack);
\r
129 if (trackIdx != mi.i_trackNo){
\r
130 u32 sampleCount = gf_isom_get_sample_count(mi.fp_in, trackIdx);
\r
131 for(u32 i=1; i<=sampleCount; i++){
\r
132 printf("... %5.1f%%\r", (double)i/(double)sampleCount * 100.0);
\r
133 GF_ISOSample *sample = gf_isom_get_sample(mi.fp_in, trackIdx, i, &readDscIdx);
\r
134 e = gf_isom_add_sample(mi.fp_out, destTrack, readDscIdx, sample);
\r
135 gf_isom_sample_del(&sample);
\r
139 //
\83^
\83C
\83\80\83X
\83P
\81[
\83\8b\90Ý
\92è
\r
140 e = gf_isom_set_media_timescale(mi.fp_out, destTrack, (u32)prm->i_timescale);
\r
142 printf("!!!
\83^
\83C
\83\80\83X
\83P
\81[
\83\8b\90Ý
\92è
\8e¸
\94s : %d !!!\n", e);
\r
144 // DTS
\82ð
\90Ý
\92è
\82µ
\8fo
\97Í
\r
145 s64 before_dts = -1;
\r
146 int delta_time = int((prm->i_timerate * prm->f_scaleFct) / (mi.i_delayFrame*2));
\r
148 if(delta_time < 1 && prm->b_dc){
\r
149 ErrorMessage(MSG_MORE_SMALL_TIMERATE);
\r
153 for(u32 i=0; i<mi.ui_sampleCount; i++){
\r
154 printf("... %5.1f%%\r", (double)i/(double)mi.ui_sampleCount * 100.0);
\r
166 cts_delay = mi.i_initDelay;
\r
168 for(u32 k=MAX(0, i - mi.i_delayFrame); k<i; k++)
\r
169 ts_diff += (int)(tsSort[k + 1].PTS - tsSort[k].PTS);
\r
171 dts_delay = MAX(mi.i_initDelay, ts_diff);
\r
175 if(dts_delay < tsSort[i].PTS)
\r
176 dts = tsSort[i].PTS - dts_delay;
\r
178 //
\91O
\89ñ
\82ÌDTS
\82æ
\82è
\82à
\92l
\82Í
\91å
\82«
\82
\82È
\82¯
\82ê
\82Î
\82È
\82ç
\82È
\82¢
\81B
\r
179 if(dts <= before_dts)
\r
180 dts = before_dts + delta_time;
\r
182 // CTS_Offset
\82Ì
\8eZ
\8fo
\r
183 offset = (int)(cts - dts + cts_delay);
\r
185 //
\83I
\83t
\83Z
\83b
\83g
\82Ì
\8cv
\8eZ
\82Å
\95\89\82É
\82È
\82Á
\82Ä
\82µ
\82Ü
\82Á
\82½
\8fê
\8d\87\r
191 ts[i].DTS = before_dts = dts;
\r
192 ts[i].CTS_Offset = offset;
\r
194 //
\83`
\83F
\83b
\83N
\r
195 if( (dts + (s64)offset - (s64)ts[0].CTS_Offset) != cts )
\r
196 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
198 GF_ISOSample *sample = gf_isom_get_sample(mi.fp_in, mi.i_trackNo, i+1, &readDscIdx);
\r
199 sample->DTS = ts[i].DTS;
\r
200 sample->CTS_Offset = ts[i].CTS_Offset;
\r
201 e = gf_isom_add_sample(mi.fp_out, destTrack, readDscIdx, sample);
\r
204 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
205 gf_isom_sample_del(&sample);
\r
208 // edts
\82Ì
\91}
\93ü
\r
209 //GF_ISOSample *sample = gf_isom_get_sample_info(mi.fp_out, destTrack, 1, NULL, NULL);
\r
210 //if(sample->CTS_Offset > 0){
\r
211 // u64 trackDur = gf_isom_get_track_duration(mi.fp_out, destTrack);
\r
212 // gf_isom_remove_edit_segments(mi.fp_out, destTrack);
\r
213 // gf_isom_append_edit_segment(mi.fp_out, destTrack, trackDur, sample->CTS_Offset, GF_ISOM_EDIT_NORMAL);
\r
215 //gf_isom_sample_del(&sample);
\r
218 printf("... %d
\83g
\83\89\83b
\83N
\8fo
\97Í
\8fI
\97¹\n", trackIdx);
\r
221 //
\8fo
\97Í
\83t
\83@
\83C
\83\8b\82ð
\95Â
\82¶
\82é
\r
222 gf_isom_clone_pl_indications(mi.fp_in, mi.fp_out);
\r
223 gf_isom_clone_root_od(mi.fp_in, mi.fp_out);
\r
225 u64 duration = gf_isom_get_duration(mi.fp_out);
\r
226 gf_isom_make_interleave(mi.fp_out, 0.5);
\r
227 gf_isom_close(mi.fp_out);
\r
230 else if (prm->i_mode == MODE_OUT){
\r
231 // TIMECODE
\82Ì
\8fo
\97Í
\r
232 if(prm->i_tcv == 2){
\r
234 if((fpout = fopen(prm->p_outfile, "wb")) != NULL){
\r
235 fprintf(fpout, "# timecode format v2\r\n");
\r
236 for(u32 i=0; i<mi.ui_sampleCount; i++){
\r
237 fprintf(fpout, "%.6lf\r\n", (double)tsSort[i].PTS / (double)mi.i_org_timescale * 1000.0);
\r
241 printf("... timecode format v2
\8fo
\97Í
\8fI
\97¹\n");
\r
243 else if(prm->i_tcv == 1){
\r
245 if((fpout = fopen(prm->p_outfile, "wb")) != NULL){
\r
246 fprintf(fpout, "# timecode format v1\r\n");
\r
247 fprintf(fpout, "Assume %.6lf\r\n", getMaximumFps(&mi, tsSort));
\r
250 double beforFps = (double)mi.i_org_timescale/(double)(tsSort[1].PTS - tsSort[0].PTS);
\r
251 for(u32 i=0; i<mi.ui_sampleCount; i++){
\r
252 fps = (double)mi.i_org_timescale/(double)(tsSort[i+1].PTS - tsSort[i].PTS);
\r
253 if (fps != beforFps){
\r
254 fprintf(fpout, "%d,%d,%.6lf\r\n",stpos, i-1, beforFps);
\r
259 if(stpos <= mi.ui_sampleCount - 1){
\r
260 fprintf(fpout, "%d,%d,%.6lf\r\n",stpos, mi.ui_sampleCount - 1, fps);
\r
264 printf("... timecode format v1
\8fo
\97Í
\8fI
\97¹\n");
\r
273 //
\83t
\83@
\83C
\83\8b\82ð
\95Â
\82¶
\82Ä
\8fI
\97¹
\r
274 gf_isom_close(mi.fp_in);
\r
276 if(ts) delete [] ts;
\r
277 if(tsSort) delete [] tsSort;
\r