OSDN Git Service

add tstools.
[rec10/rec10-git.git] / tstools / DtsEdit / src / EditMain.cpp
1 #include <stdio.h>\r
2 #include "stdafx.h"\r
3 #include "Help.h"\r
4 #include "EditMain.h"\r
5 #include "debug.h"\r
6 \r
7 \r
8 void EditMain(T_EDIT_PARAM *prm){\r
9 \r
10         GF_Err          e;\r
11         T_MP4_INFO      mi;\r
12         T_TS_LIST       *ts             = NULL;\r
13         T_TS_LIST       *tsSort = NULL;\r
14 \r
15         // \8f\89\8aú\89»\r
16         gf_sys_init();\r
17 \r
18         ZeroMemory(&mi, sizeof(T_MP4_INFO));\r
19 \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
23 \r
24         mi.i_trackCount = gf_isom_get_track_count(mi.fp_in);\r
25         \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
29 \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
33                 goto _ERROR_RET;\r
34         }\r
35 \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
40                 goto _ERROR_RET;\r
41         }\r
42 \r
43         ts = new T_TS_LIST[mi.ui_sampleCount + 1];\r
44         ZeroMemory(ts, sizeof(T_TS_LIST) * mi.ui_sampleCount);\r
45 \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
49                 goto _ERROR_RET;\r
50 \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
55 \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
63 \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
66 \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
70 \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
76                 }\r
77 \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
81                                 goto _ERROR_RET;\r
82                 } else if(prm->i_tcv == 2){\r
83                         if(readTimeCodeFromFile(&mi, tsSort, prm))\r
84                                 goto _ERROR_RET;\r
85                 } else {\r
86                         goto _ERROR_RET;\r
87                 }\r
88 \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
92                 }\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
95 \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
99 \r
100 \r
101                 // \8fî\95ñ\82Ì\95\\8e¦\r
102                 printf("\n");\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
109                 printf("\n");\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
114                 printf("\n");\r
115                 printf("\83t\83@\83C\83\8b\8fo\97Í\92\86... [%s]\n", prm->p_outfile);\r
116 \r
117                 u32 readDscIdx = 0;\r
118                 u32 destTrack = 0;\r
119                 mi.fp_out = gf_isom_open(prm->p_outfile, GF_ISOM_OPEN_WRITE, NULL);\r
120 \r
121 \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
128 \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
136                                 }\r
137 \r
138                         } else {\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
141                                 if(e)\r
142                                         printf("!!! \83^\83C\83\80\83X\83P\81[\83\8b\90Ý\92è\8e¸\94s : %d !!!\n", e);\r
143 \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
147 \r
148                                 if(delta_time < 1 && prm->b_dc){\r
149                                         ErrorMessage(MSG_MORE_SMALL_TIMERATE);\r
150                                         break;\r
151                                 }\r
152 \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
155 \r
156                                         s64 cts = 0;\r
157                                         s64 dts = 0;\r
158                                         int offset = 0;\r
159                                         int dts_delay = 0;\r
160                                         int cts_delay = 0;\r
161                                         int ts_diff = 0;\r
162 \r
163                                         cts = ts[i].PTS;\r
164                                         if(!prm->b_dc){\r
165                                                 dts_delay = 0;\r
166                                                 cts_delay = mi.i_initDelay;\r
167                                         } else {\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
170 \r
171                                                 dts_delay = MAX(mi.i_initDelay, ts_diff);\r
172                                                 cts_delay = 0;\r
173                                         }\r
174 \r
175                                         if(dts_delay < tsSort[i].PTS)\r
176                                                 dts = tsSort[i].PTS - dts_delay;\r
177 \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
181 \r
182                                         // CTS_Offset\82Ì\8eZ\8fo\r
183                                         offset = (int)(cts - dts + cts_delay);\r
184 \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
186                                         if (offset < 0){\r
187                                                 dts += offset;\r
188                                                 offset = 0;\r
189                                         }\r
190 \r
191                                         ts[i].DTS = before_dts = dts;\r
192                                         ts[i].CTS_Offset = offset;\r
193 \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
197 \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
202 \r
203                                         if(e)\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
206                                 }\r
207 \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
214                                 //}\r
215                                 //gf_isom_sample_del(&sample);\r
216                         }\r
217 \r
218                         printf("... %d\83g\83\89\83b\83N\8fo\97Í\8fI\97¹\n", trackIdx);\r
219                 }\r
220 \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
224 \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
228 \r
229         }\r
230         else if (prm->i_mode == MODE_OUT){\r
231                 // TIMECODE\82Ì\8fo\97Í\r
232                 if(prm->i_tcv == 2){\r
233                         FILE *fpout;\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
238                                 }\r
239                         }\r
240                         fclose(fpout);\r
241                         printf("... timecode format v2 \8fo\97Í\8fI\97¹\n");\r
242                 }\r
243                 else if(prm->i_tcv == 1){\r
244                         FILE *fpout;\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
248                                 u32 stpos = 0;\r
249                                 double fps = 0.0;\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
255                                                 beforFps = fps;\r
256                                                 stpos = i;\r
257                                         }\r
258                                 }\r
259                                 if(stpos <= mi.ui_sampleCount - 1){\r
260                                         fprintf(fpout, "%d,%d,%.6lf\r\n",stpos, mi.ui_sampleCount - 1, fps);\r
261                                 }\r
262                         }\r
263                         fclose(fpout);\r
264                         printf("... timecode format v1 \8fo\97Í\8fI\97¹\n");\r
265                 } else {\r
266                         goto _ERROR_RET;\r
267                 }\r
268         }\r
269 \r
270 \r
271 _ERROR_RET:\r
272 \r
273         // \83t\83@\83C\83\8b\82ð\95Â\82\82Ä\8fI\97¹\r
274         gf_isom_close(mi.fp_in);\r
275 \r
276         if(ts)          delete [] ts;\r
277         if(tsSort)      delete [] tsSort;\r
278         // \8dÅ\8fI\r
279         gf_sys_close();\r
280 }\r
281 \r