OSDN Git Service

modify Usage
[cmcheckwave/cmcheckwave.git] / cmcheckwave.c
1 /*********************************************************************
2   original base program  http://oku.edu.mie-u.ac.jp/~okumura/dumpwave.c
3
4   cmcheckwave.c
5
6 Usage: cmcheckwave filename.wav
7  *********************************************************************/
8
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <unistd.h>
13 #include <assert.h>
14
15 #include "tclist.h"
16
17 static void usage(char *cmd){
18         fprintf(stderr,"Check CM from wavefile(output cmd stdout)\n");
19         fprintf(stderr,"%s: filename.wav\n\n",cmd);
20         fprintf(stderr,"Check CM from mp4file(require ffmpeg cmd)\n");
21         fprintf(stderr,"%s: filename.mp4\n\n",cmd);
22         fprintf(stderr,"Check CM from mp4file and execute cutcmd(create new filename.mp4-new.mp4) \n");
23         fprintf(stderr,"%s: -x filename.mp4\n\n",cmd);
24         fprintf(stderr,"Check CM and manual edit\n");
25         fprintf(stderr,"%s: -b filename.mp4 filename.mp4 > filename-sh\n",cmd);
26         fprintf(stderr,"Edit filename-sh for mis detection and re execute next cmd\n",cmd);
27         fprintf(stderr,"%s: -x filename-sh\n",cmd);
28         exit(1);
29 }
30
31 unsigned char *get_bytes(FILE *f, int n)
32 {
33         static unsigned char s[16];
34
35         assert (n <= sizeof s);
36         if (fread(s, n, 1, f) != 1) {
37                 fprintf(stderr, "Read error\n");
38                 exit(1);
39         }
40         return s;
41 }
42
43 unsigned long get_ulong(FILE *f)
44 {
45         unsigned char *s = get_bytes(f, 4);
46         return s[0] + 256LU * (s[1] + 256LU * (s[2] + 256LU * s[3]));
47 }
48
49 unsigned get_ushort(FILE *f)
50 {
51         unsigned char *s = get_bytes(f, 2);
52         return s[0] + 256U * s[1];
53 }
54
55 typedef struct {
56         int  stsec;
57         int  edsec;
58         int  diffs;
59         char cmflg;
60         char honpen;
61         int  peak;
62 }muonst;
63
64 static muonst m[1000];
65 static muonst h[100];
66 static int verbose=0;
67 static int noaudioencode=0;
68 static char *wkfilename=NULL;
69 static int defmuon=250;
70 static int defmax=9;
71 static int thumb=0;
72 static int txtrecheck=0;
73 static int cmdexecute=0;
74 static int checkcomplete=0;
75
76 static char *MP4BOXCMDRAPSTR="Adjusting chunk start time to previous random access at ";
77 #ifdef __FreeBSD__
78 static char *MP4BOXCMD="/usr/local/bin/MP4Box";
79 static char *SOXCMD="/usr/local/bin/sox";
80 static char *FFMPEGCMD="/usr/local/bin/ffmpeg";
81 static char *MPLAYERCMD="/usr/local/bin/mplayer";
82 static char *AACENCCMD="/usr/local/bin/aacplusenc";
83 static char *AACENCOPT="%s '%s.wav' '%s' 60";
84 static char *FAADCMD=NULL;
85 #else
86 static char *MP4BOXCMD="mp4box";
87 static char *SOXCMD="sox";
88 static char *FFMPEGCMD="ffmpeg";
89 static char *MPLAYERCMD="mplayer";
90 static char *AACENCCMD="neroAacEnc";
91 static char *AACENCOPT="%s -hev2 -br 60 -if '%s.wav' -of '%s'";
92 static char *FAADCMD=NULL;
93 #endif
94
95 FILE *checkMP4(FILE *f,char *filename)
96 {
97         char readbuf[20];
98         char *cmdbuf;
99         FILE *pp;
100
101         memset(readbuf,0,sizeof(readbuf));
102         fread(readbuf,sizeof(readbuf),1,f);
103         rewind(f);
104         if (!strstr(readbuf+4,"ftypisom")) {
105                 return NULL;
106         }
107         // mp4ファイルだったら、ffmpegでwaveに変換し読み込む。
108         asprintf(&cmdbuf,"%s -v 0 -i '%s' -f wav pipe: 2>/dev/null",FFMPEGCMD,filename);
109 #if 0
110         // FFMPEG-> aac-> faad ?
111         asprintf(&cmdbuf,"%s -d -w -q '%s%'",FAADCMD,filename);
112 #endif
113         pp = popen(cmdbuf,"r");
114         if (pp == NULL) return NULL;
115         fclose(f);
116         wkfilename = strdup(filename);
117         return pp;
118 }
119
120 FILE *openpipeffmpeg(char *filename)
121 {
122         char cmdbuf[1024];
123         FILE *pp;
124
125
126
127 }
128
129 int checkMP4RAP(int stsec,int edsec)
130 {
131         FILE *pp;
132         char pbuf[1024];
133         char cmdbuf[1024];
134         float rap;
135
136         if (wkfilename==NULL) return stsec;
137
138         sprintf(cmdbuf,"%s -quiet -noprog -splitx %.2f:%.2f '%s' -out /dev/null",MP4BOXCMD,edsec/1000.0,(edsec+10000)/1000.0,wkfilename);
139
140         rap=0.0;
141         pp = popen(cmdbuf,"r");
142         if (pp == NULL) return stsec;
143         while(fgets(pbuf,1024,pp)!=NULL){
144                 if (strstr(pbuf,MP4BOXCMDRAPSTR)) {
145                         sscanf(pbuf+strlen(MP4BOXCMDRAPSTR),"%f",&rap);
146                         //TODO rapはCM開始フレームの秒数なのでちょっと戻す。
147                         //     フレームレートとか調べないとだめだな・・・
148                         rap = rap - 0.04;
149                 }
150         }
151         pclose(pp);
152         if (rap > 0 && stsec < rap*1000.0) return rap*1000.0;
153         else return stsec;
154
155 }
156 int cmpinfo(int mcnt)
157 {
158         int i;
159         char *cmdptr,readbuf[20];
160         TCLIST *cmdlist;
161
162         if (!wkfilename) return 0;
163
164         cmdlist = tclistnew();
165
166         asprintf(&cmdptr,"#!/bin/sh");
167         tclistpush2(cmdlist,cmdptr);
168         free(cmdptr);
169
170
171         for(i=0;i<mcnt;i++) {
172                 if (thumb) {
173                         asprintf(&cmdptr,"rm -f '%s-%d.png'",wkfilename,i);
174                         tclistpush2(cmdlist,cmdptr);
175                         free(cmdptr);
176                 }
177         }
178         // check new mp4
179         asprintf(&cmdptr,"%s-new.mp4",wkfilename);
180         FILE *fp;
181         fp = fopen(cmdptr,"rb");
182         if (fp==NULL) {
183                 //ファイルなし
184                 return 0;
185         }
186         fread(readbuf,sizeof(readbuf),1,fp);
187         if (!strstr(readbuf+4,"ftypisom")) {
188                 //mp4じゃない感じ(置き換えないときは無視)
189                 if (checkcomplete == 1) return 0;
190         }
191         fclose(fp);
192         free(cmdptr);
193
194         if (checkcomplete==1) { //元ファイル置き換え
195                 asprintf(&cmdptr,"mv '%s-new.mp4' '%s'",wkfilename,wkfilename);
196                 tclistpush2(cmdlist,cmdptr);
197                 free(cmdptr);
198         }
199         if (checkcomplete==2) { //CMカットファイル削除
200                 asprintf(&cmdptr,"rm -f '%s-new.mp4'",wkfilename);
201                 tclistpush2(cmdlist,cmdptr);
202                 free(cmdptr);
203         }
204
205         asprintf(&cmdptr,"rm -f '%s-sh'",wkfilename);
206         tclistpush2(cmdlist,cmdptr);
207         free(cmdptr);
208
209         asprintf(&cmdptr,"rm -f '%s.split.log'",wkfilename);
210         tclistpush2(cmdlist,cmdptr);
211         free(cmdptr);
212
213         for(i=0;i<tclistnum(cmdlist);i++) {
214                 if (cmdexecute) {
215                         FILE *pp;
216                         char pbuf[1024];
217                         pp = popen(tclistval2(cmdlist,i),"r");
218                         if (pp==NULL) {continue;}
219                         while(fgets(pbuf,1024,pp)!=NULL){
220                         }
221                         pclose(pp);
222                 }
223                 else
224                         printf("%s\n",tclistval2(cmdlist,i));
225         }
226
227 }
228 int dumpinfo(int mcnt)
229 {
230         int honstart,hcnt,totalsec;
231         int i,pre;
232         char *cptr,*cptr2,*tfptr;
233         TCLIST *cmdlist;
234         TCLIST *tflist;
235
236         honstart=0;
237         hcnt=0;
238         totalsec=0;
239         printf("#!/bin/sh\n# cmcheckwave %s\n#\n",wkfilename?wkfilename:"");
240         //カットするため、一連のCM,本編時間を結合
241         for(i=0;i<mcnt;i++) {
242                 printf("# %.2f %.2f diff %.2f %s\n",m[i].stsec/1000.0,m[i].edsec/1000.0,m[i].diffs/1000.0,m[i].cmflg?"CM":"");
243                 //本編開始位置をマーク
244                 if ((m[i].cmflg==0)&&(honstart==0)) {
245                         honstart=1;
246                         if (i==0) h[hcnt].stsec = 0;
247                         else h[hcnt].stsec = m[i-1].edsec+(defmuon*0.5);
248                 }
249                 else {
250                         //終了位置をマーク
251                         if ((m[i].cmflg==1)&&(honstart==1)) {
252                                 honstart=0;
253                                 //h[hcnt].edsec = m[i-1].stsec;
254                                 h[hcnt].edsec = checkMP4RAP(m[i-1].stsec,m[i-1].edsec);
255                                 totalsec += h[hcnt].edsec - h[hcnt].stsec;
256                                 hcnt++;
257                         }
258                 }
259         }
260         if (honstart==1) {
261                 h[hcnt].edsec = checkMP4RAP(m[i-1].stsec,m[i-1].edsec);
262                 totalsec += h[hcnt].edsec - h[hcnt].stsec;
263                 hcnt++;
264         }
265
266         printf("# total %.2f\n\n",totalsec/1000.0);
267
268         cmdlist = tclistnew();
269         tflist = tclistnew();
270         if (wkfilename) {
271                 asprintf(&cptr,"rm -f '%s.split.log'",wkfilename);
272                 tclistpush2(cmdlist,cptr);
273                 free(cptr);
274         }
275         for(i=0;i<hcnt;i++) {
276                 if (wkfilename) {
277                         asprintf(&tfptr,"%s.%d%s",wkfilename,i,noaudioencode?".mp4":"");
278                         asprintf(&cptr,"%s -quiet -noprog -splitx %.2f:%.2f '%s' -out '%s' >> '%s.split.log'",MP4BOXCMD,h[i].stsec/1000.0,h[i].edsec/1000.0,wkfilename,tfptr,wkfilename);
279                         tclistpush2(cmdlist,cptr);
280                         tclistpush2(tflist,tfptr);
281                         free(tfptr);
282                         free(cptr);
283
284                         if (!noaudioencode) {
285                                 asprintf(&tfptr,"%s.%d.wav",wkfilename,i);
286
287                                 if (FAADCMD)
288                                         asprintf(&cptr,"%s -v 0 -i '%s.%d' -vn -acodec copy '%s.aac';%s -d -q -o '%s' '%s.aac' ",FFMPEGCMD,wkfilename,i,tfptr,FAADCMD,tfptr,tfptr);
289                                 else
290                                         asprintf(&cptr,"%s -v 0 -i '%s.%d' -vn '%s'",FFMPEGCMD,wkfilename,i,tfptr);
291                                 tclistpush2(cmdlist,cptr);
292                                 tclistpush2(tflist,tfptr);
293                                 free(tfptr);
294                                 free(cptr);
295                                 if (FAADCMD) {
296                                         asprintf(&tfptr,"%s.%d.wav.aac",wkfilename,i);
297                                         tclistpush2(tflist,tfptr);
298                                         free(tfptr);
299                                 }
300
301                                 asprintf(&tfptr,"%s.%d.mp4",wkfilename,i);
302                                 asprintf(&cptr,"%s -v 0 -i '%s.%d' -an -vcodec copy '%s'",FFMPEGCMD,wkfilename,i,tfptr);
303                                 tclistpush2(cmdlist,cptr);
304                                 tclistpush2(tflist,tfptr);
305                                 free(tfptr);
306                                 free(cptr);
307                         }
308                 }
309                 else {
310                         asprintf(&cptr,"# %s -quiet -noprog -splitx %.2f:%.2f ",MP4BOXCMD,h[i].stsec/1000.0,h[i].edsec/1000.0);
311                         tclistpush2(cmdlist,cptr);
312                 }
313         }
314         if (wkfilename) {
315                 if (!noaudioencode) {
316                         asprintf(&cptr2,"%s --norm ",SOXCMD);
317                         for(i=0;i<hcnt;i++) {
318                                 asprintf(&tfptr,"%s.%d.wav",wkfilename,i);
319                                 asprintf(&cptr,"%s '%s' ",cptr2,tfptr);
320                                 free(cptr2);
321                                 cptr2=cptr;
322                                 tclistpush2(tflist,tfptr);
323                                 free(tfptr);
324                         }
325                         asprintf(&tfptr,"%s.wav",wkfilename);
326                         asprintf(&cptr,"%s '%s'",cptr2,tfptr);
327                         free(cptr2);
328                         tclistpush2(cmdlist,cptr);
329                         tclistpush2(tflist,tfptr);
330                         free(tfptr);
331
332                         asprintf(&tfptr,"%s.aac",wkfilename);
333                         asprintf(&cptr,AACENCOPT,AACENCCMD,wkfilename,tfptr);
334                         tclistpush2(cmdlist,cptr);
335                         free(cptr);
336                         tclistpush2(tflist,tfptr);
337                         free(tfptr);
338                 }
339                 //ファイル名-new.mp4ファイルを削除する
340                 asprintf(&cptr,"rm -f '%s-new.mp4'",wkfilename);
341                 tclistpush2(cmdlist,cptr);
342                 free(cptr);
343
344                 asprintf(&cptr2,"%s -quiet -noprog ",MP4BOXCMD);
345                 for(i=0;i<hcnt;i++) {
346                         asprintf(&cptr,"%s -cat '%s.%d.mp4' ",cptr2,wkfilename,i);
347                         free(cptr2);
348                         cptr2=cptr;
349                 }
350                 asprintf(&cptr,"%s '%s-new.mp4'",cptr2,wkfilename);
351                 tclistpush2(cmdlist,cptr);
352                 free(cptr);
353
354                 if (!noaudioencode) {
355                         asprintf(&cptr,"%s -quiet -noprog -add '%s.aac' '%s-new.mp4'",MP4BOXCMD,wkfilename,wkfilename);
356                         tclistpush2(cmdlist,cptr);
357                 }
358
359
360                 for(i=0;i<tclistnum(tflist);i++) {
361                         asprintf(&cptr,"rm -f '%s'",tclistval2(tflist,i));
362                         tclistpush2(cmdlist,cptr);
363                         free(cptr);
364                 }
365
366                 if (thumb) {
367                         pre=0;
368                         for(i=0;i<mcnt;i++) {
369                                 asprintf(&cptr,"%s -ao null -ss %.2f -frames 1 -vo png:z=9  '%s' ; mv 00000001.png '%s-%d.png'",MPLAYERCMD,(pre + (m[i].stsec-pre)/2)/1000.0,wkfilename,wkfilename,i);
370                                 tclistpush2(cmdlist,cptr);
371                                 pre = m[i].stsec;
372                         }
373                 }
374         }
375
376         for (i=0;i<tclistnum(cmdlist);i++) {
377                 if (cmdexecute && wkfilename) {
378                         FILE *pp;
379                         char pbuf[1024];
380                         pp = popen(tclistval2(cmdlist,i),"r");
381                         if (pp==NULL) {continue;}
382                         while(fgets(pbuf,1024,pp)!=NULL){
383                         }
384                         pclose(pp);
385                 }
386                 else
387                         printf("%s\n",tclistval2(cmdlist,i));
388         }
389
390 }
391
392 int rechecktext(FILE *f)
393 {
394         char rbuf[1024];
395         char fname[1024];
396         char cm[100];
397         char wk1[100];
398         char wk2[100];
399         char wk3[100];
400         char wk4[100];
401         int cnt,pgst,len;
402         float in1,in2,in3;
403
404
405         rewind(f);
406         cnt=0;
407
408         pgst=0;
409         fname[0]=0x00;
410
411         while(fgets(rbuf,1024,f)!=NULL){
412                 if (strstr(rbuf,"# cmcheckwave ")) {
413                         pgst=1;
414                         if (strlen(rbuf+14)-1>0) {
415                                 wkfilename = malloc(strlen(rbuf+14));
416                                 strncpy(wkfilename,rbuf+14,strlen(rbuf+14)-1);
417                         }
418                         fgets(rbuf,1024,f);
419                         continue;
420                 }
421                 if (strstr(rbuf,"# total "))
422                         pgst=0;
423                 if (pgst) {
424                         wk4[0]=0x00;
425                         sscanf(rbuf,"# %s %s diff %s %s",wk1,wk2,wk3,wk4);
426
427                         m[cnt].stsec = (int)(atof(wk1)*1000.0);
428                         m[cnt].edsec = (int)(atof(wk2)*1000.0);
429                         m[cnt].diffs = (int)(atof(wk3)*1000.0);
430                         if (strstr(wk4,"CM")) m[cnt].cmflg=1;
431                         else m[cnt].cmflg=0;
432                         m[cnt].honpen = 0;
433                         cnt++;
434                 }
435
436         }
437         if (checkcomplete > 0) {
438                 return cmpinfo(cnt);
439         }
440         txtrecheck=1;
441         return dumpinfo(cnt);
442
443
444 }
445
446 int cmcheckwave(FILE *f)
447 {
448         int i,j, x, channels, bits;
449         unsigned long len;
450         long count;
451         unsigned char s[5];
452         unsigned long bsec;
453         int readed,loop,max,totalsec,muonstartsec,kankaku;
454         double dul,diffs;
455         char cm[10];
456         int mcnt,hcnt,rcnt,readbufsz;
457         unsigned char *readbuf;
458         int honstart;
459         int cmwork;
460         int peak;
461
462         if (memcmp(get_bytes(f, 4), "RIFF", 4) != 0) {
463                 //   fprintf(stderr, "Not a 'RIFF' format\n");
464                 return -1;
465         }
466         //fprintf(stderr, "[RIFF] (%lu bytes)\n", get_ulong(f));
467         get_ulong(f);
468         if (memcmp(get_bytes(f, 8), "WAVEfmt ", 8) != 0) {
469                 // fprintf(stderr, "Not a 'WAVEfmt ' format\n");
470                 return -1;
471         }
472         len = get_ulong(f);
473         //fprintf(stderr, "[WAVEfmt ] (%lu bytes)\n", len);
474         //fprintf(stderr, "  Data type = %u (1 = PCM)\n", get_ushort(f));
475         get_ushort(f);
476         channels = get_ushort(f);
477         //fprintf(stderr, "  Number of channels = %u (1 = mono, 2 = stereo)\n", channels);
478         //fprintf(stderr, "  Sampling rate = %luHz\n", get_ulong(f));
479         get_ulong(f);
480         bsec = get_ulong(f);
481         //fprintf(stderr, "  Bytes / second = %lu\n", bsec);
482         //fprintf(stderr, "  Bytes x channels = %u\n", get_ushort(f));
483         get_ushort(f);
484         bits = get_ushort(f);
485         //fprintf(stderr, "  Bits / sample = %u\n", bits);
486         for (i = 16; i < len; i++)
487                 fgetc(f);
488         while (fread(s, 4, 1, f) == 1) {
489                 len = get_ulong(f);
490                 s[4] = 0;
491                 //fprintf(stderr, "[%s] (%lu bytes)\n", s, len);
492                 if (memcmp(s, "data", 4) == 0) break;
493                 for (i = 0; i < len; i++)
494                         fgetc(f);
495         }
496
497         readed=max=totalsec=kankaku=mcnt=0;
498         peak=0;
499         muonstartsec=-1;
500         loop=1;
501         readbuf=malloc(4096*1000);
502         while(rcnt=fread(readbuf,1,4096*1000,f)) {
503                 for(readbufsz=0;readbufsz<rcnt;) {
504                         for (i = 0; i < channels; i++) {
505                                 if (bits <= 8) {
506                                         //if ((x = fgetc(f)) == EOF) {loop=0;break;}
507                                         x = readbuf[readbufsz];
508                                         readed++;
509                                         readbufsz++;
510                                         x -= 128;
511                                 } else {
512                                         //if (fread(s, 2, 1, f) != 1) {loop=0;break;}
513                                         //x = (short)(s[0] + 256 * s[1]);
514                                         x = (short)(readbuf[readbufsz+0] + 256 * readbuf[readbufsz+1]);
515                                         readed+=2;
516                                         readbufsz+=2;
517                                 }
518                                 if (x > max) max = x;
519                                 if (x > peak) peak = x;
520                                 //printf("%d", x);
521                                 //if (i != channels - 1) printf("\t");
522                         }
523                         //printf("\n");
524                         if (readed % (bsec/100) == 0) {
525                                 //無音開始
526                                 if (muonstartsec==-1 && max < defmax) {
527                                         muonstartsec = totalsec;
528                                 }
529                                 else {
530                                         // 無音終わり
531                                         if (muonstartsec>=0 && max >= defmax) {
532                                                 // 無音が300(defmuon)msより大きい
533                                                 if (totalsec - muonstartsec > defmuon){
534
535                                                         m[mcnt].stsec = muonstartsec;
536                                                         m[mcnt].edsec = totalsec;
537                                                         m[mcnt].diffs = totalsec - kankaku;
538                                                         m[mcnt].cmflg = 0;
539                                                         m[mcnt].honpen = 0;
540
541                                                         dul = (totalsec-muonstartsec)/1000.0;
542                                                         diffs = (totalsec-kankaku)/1000.0;
543
544                                                         if ((diffs >  14.5) && (diffs < 15.5)) m[mcnt].cmflg=1;
545                                                         if ((diffs >  29.5) && (diffs < 30.5)) m[mcnt].cmflg=1;
546                                                         if ((diffs >  59.5) && (diffs < 60.5)) m[mcnt].cmflg=1;
547
548                                                         kankaku=totalsec;
549                                                         m[mcnt].peak=peak;
550                                                         mcnt++;
551
552                                                         peak=0;
553                                                 }
554                                                 muonstartsec=-1;
555                                         }
556                                 }
557                                 max=0;
558                                 totalsec += 10;
559                         }
560                 }
561         }
562         if (mcnt > 1) {
563                 //本編前CMチェック
564                 if ((m[0].cmflg==0) && (m[0].diffs < 15000))
565                         m[0].cmflg=1;
566                 //細切れCMのたしこみ
567                 for(i=1;i<mcnt-1;i++) {
568                         // 本編で31秒以下が連続だったら、次の31秒以上の本編もしくはCMまでの時間をチェック
569                         // 足しこみは61秒まで
570                         // TODO 28+32で60秒CMとかいうのがあるどうするのがいいだろうか・・・
571                         if (m[i].cmflg==0 && m[i].diffs < 31000  && m[i+1].cmflg==0 && m[i+1].diffs < 31000) {
572                                 cmwork=0;
573                                 for(j=i;j<mcnt;j++) {
574                                         if (m[j].cmflg==1) break;
575                                         if (m[j].diffs > 31000) break;
576                                         if (cmwork + m[j].diffs > 61000) break;
577                                         cmwork = cmwork + m[j].diffs;
578                                 }
579                                 //合計時間を15秒で割ってcm時間っぽいならばCMとする。
580                                 // TODO 30(15)秒以下の条件付けがいる?60秒どうする?
581                                 if (cmwork%15000>14500 || cmwork%15000<500) {
582                                         for(j=i;j<mcnt;j++) {
583                                                 if (m[j].cmflg==1) break;
584                                                 if (m[j].diffs > 31000) break;
585                                                 m[j].cmflg=1;
586                                         }
587                                 }
588                         }
589
590                 }
591                 // 最終CMチェック
592                 if ((m[mcnt-1].cmflg==0) && (m[mcnt-1].diffs < 15000))
593                         m[mcnt-1].cmflg=1;
594                 //短い本編・提供などの処理
595                 for(i=1;i<mcnt-1;i++) {
596                         //本編で46秒以下かつ、前後がCMの場合CM14-16,29-31,44-46秒でもCMとする。
597                         if (m[i].cmflg==0 && m[i].diffs < 46000 && m[i-1].cmflg==1 && m[i+1].cmflg==1) {
598                                 if ((m[i].diffs > 14000) && (m[i].diffs < 16000)) m[i].cmflg=1;
599                                 if ((m[i].diffs > 29000) && (m[i].diffs < 31000)) m[i].cmflg=1;
600                                 if ((m[i].diffs > 44000) && (m[i].diffs < 46000)) m[i].cmflg=1;
601                                 // 0.9秒以下(おそらく前後CMのあまり時間)
602                                 if (m[i].diffs < 900) m[i].cmflg=1;
603
604                                 //10,5秒のときは提供とみなし、その前を本編にする。
605                                 //TODO 15秒提供は判別不能・・・
606                                 if ((m[i].diffs > 9500) && (m[i].diffs < 10500)) m[i-1].cmflg=0;
607                                 if ((m[i].diffs > 4500) && (m[i].diffs < 5500)) m[i-1].cmflg=0;
608                         }
609                         // TODO 前後が本編で単独でCMの場合は本編とする?
610                         // 46秒以下のチェックも?
611                         // if (m[i].cmflg==1 && m[i-1].cmflg==0 && m[i+1].cmflg==0) {
612                         //      m[i].cmflg=0;
613                         // }
614                 }
615
616         }
617         return dumpinfo(mcnt);
618 }
619
620 int main(int argc, char *argv[])
621 {
622         extern char *optarg;
623         extern int optind, opterr;
624         int i,ch;
625         FILE *f,*p;
626         int ret;
627         char *tmpenv,*argv0;
628         ret = -1;
629
630         argv0 = argv[0];
631         while ((ch = getopt(argc, argv, "adtxb:m:v:c:")) != -1){
632                 switch (ch){
633                         case 'a':
634                                 noaudioencode=1;
635                                 break;
636                         case 'd':
637                                 verbose=1;
638                                 break;
639                         case 'b':
640                                 wkfilename=optarg;
641                                 break;
642                         case 'm':
643                                 defmuon=atoi(optarg);
644                                 break;
645                         case 'v':
646                                 defmax=atoi(optarg);
647                                 break;
648                         case 't':
649                                 thumb=1;
650                                 break;
651                         case 'x':
652                                 cmdexecute=1;
653                                 break;
654                         case 'c':
655                                 checkcomplete=atoi(optarg);
656                                 if (checkcomplete <= 0 && checkcomplete > 2) usage(argv0);
657                                 break;
658                         default:
659                                 usage(argv0);
660                 }
661         }
662         argc -= optind;
663         argv += optind;
664
665         if (argc != 1) {
666                 usage(argv0);
667                 return 0;
668         }
669         if (tmpenv=getenv("FFMPEG")) FFMPEGCMD=tmpenv;
670         if (tmpenv=getenv("SOX")) SOXCMD=tmpenv;
671         if (tmpenv=getenv("MP4BOX")) MP4BOXCMD=tmpenv;
672         if (tmpenv=getenv("MP4BOXCMDRAPSTR")) MP4BOXCMDRAPSTR=tmpenv;
673         if (tmpenv=getenv("AACENC")) AACENCCMD=tmpenv;
674         if (tmpenv=getenv("AACENCPOT")) AACENCOPT=tmpenv;
675         if (tmpenv=getenv("MPLAYER")) MPLAYERCMD=tmpenv;
676         if (tmpenv=getenv("FAADCMD")) FAADCMD=tmpenv;
677
678         ret=0;
679         p=NULL;
680         if (strcmp(argv[0],"-")==0)
681                 f = stdin;
682         else {
683                 f = fopen(argv[0],"rb");
684                 if (f) {
685                         p = checkMP4(f,argv[0]);
686                 }
687                 else
688                         return -1;
689         }
690
691         if (p)  ret = cmcheckwave(p);
692         else    ret = cmcheckwave(f);
693         // -1 のときはテキストとして再チェック
694         if (ret == -1) rechecktext(f);
695         if (p) pclose(p);
696         else fclose(f);
697
698         return ret;
699 }
700
701
702
703