20 long dsofs = 0, deofs = 0;
21 char *xfn = 0, *ofn = 0;
22 FILE *xfp = 0, *ofp = 0;
28 static int cmpr(const void *ap, const void *bp);
29 Edit(long st, long len, long ofs) : start(st), length(len), offset(ofs) {}
30 long sfrm() { return start; }
31 long efrm() { return start+length-1; }
32 long ofrm(long frm) { return frm-start+offset; }
36 int Edit::cmpr(const void *ap, const void *bp)
38 Edit *a = *(Edit **)ap;
39 Edit *b = *(Edit **)bp;
40 int n = a->sfrm() - b->sfrm();
41 if( !n ) n = a->length - b->length;
50 Edits() : count(0), allocated(0), list(0), pos(0) {}
51 ~Edits() { for( int i=0; i<count; ++i ) delete list[i]; }
52 void append(long st, long len);
53 bool finished(long frm) { return count>0 && frm>=list[count-1]->efrm(); }
54 Edit *active(long frm);
55 void sort() { qsort(list, count, sizeof(Edit*), Edit::cmpr); }
56 int len() { return count; }
59 void Edits::append(long st, long len)
61 if( count >= allocated ) {
62 int sz = 2*allocated + 16;
63 Edit **new_list = new Edit*[sz];
64 for( int i=0; i<count; ++i ) new_list[i] = list[i];
65 delete list; list = new_list; allocated = sz;
67 list[count++] = new Edit(st, len, pos);
71 Edit *Edits::active(long frm)
78 if( frm < mp->sfrm() ) l = m;
79 else if( frm > mp->sfrm() ) h = m;
83 if( frm < mp->sfrm() ) return 0;
84 if( frm > mp->efrm() ) return 0;
91 fprintf(stderr,"usage: %s ",prog);
92 fprintf(stderr," [-c cc_service ] ");
93 fprintf(stderr," [-s start:length, ...] ");
94 fprintf(stderr," [ -t track ] ");
95 fprintf(stderr," [-v verbose ]\n");
97 fprintf(stderr," [-w wdw mask ] ");
98 fprintf(stderr," [-x file.xml ] ");
99 fprintf(stderr," [-o file.udvd ] ");
100 fprintf(stderr," file.ts\n");
101 fprintf(stderr," cc_service = closed caption service id\n");
102 fprintf(stderr," start:length = start:length frames (comma seperated list)\n");
103 fprintf(stderr," track = video track number\n");
104 fprintf(stderr," verbose = verbose level\n");
105 fprintf(stderr," wdw mask = bit mask for windows (-1 = all)\n");
106 fprintf(stderr," file.xml = filename for edl xml format subtitle data\n");
107 fprintf(stderr," file.udvd = filename for udvd format subtitle data\n");
108 fprintf(stderr," file.ts = filename for transport stream\n");
114 fprintf(xfp,"<?xml version=\"1.0\"?>\n");
115 fprintf(xfp,"<EDL VERSION=4.4 PATH=%s>\n", xfn);
116 fprintf(xfp," <TRACK RECORD=1 NUDGE=0 PLAY=1 GANG=1 DRAW=1 EXPAND=0");
117 fprintf(xfp," TRACK_W=0 TRACK_H=0 TYPE=SUBTTL>\n");
118 fprintf(xfp,"<TITLE>Subttl 1</TITLE>\n");
119 fprintf(xfp,"<EDITS>\n");
122 void edit_data(const char *sp, int n, int len)
124 const char *cp, *ep = sp + n;
125 fprintf(xfp,"<EDIT STARTSOURCE=0 CHANNEL=0 LENGTH=%d TEXT=\"", len);
129 case '<': cp = "<"; break;
130 case '>': cp = ">"; break;
131 case '&': cp = "&"; break;
132 case '"': cp = """; break;
133 default: fputc(ch, xfp); continue;
135 while( *cp != 0 ) fputc(*cp++, xfp);
137 fprintf(xfp,"\"></EDIT>\n");
145 if( (df=dsofs-fpos) > 0 ) edit_data("", 0, df);
146 if( (df=deofs-dsofs) > 0 ) edit_data(dfrm, dlen, df);
152 if( dlen > 0 ) edit_write();
153 fprintf(xfp,"</EDITS>\n");
154 fprintf(xfp,"</TRACK>\n");
155 fprintf(xfp,"</EDL>\n");
158 int text_cb(int sid, int id, int sfrm, int efrm, const char *txt)
160 long sofs = sfrm, eofs = efrm;
161 if( ((1<<id) & wdw_mask) == 0 ) return 0;
162 if( edits.finished(sfrm) ) { done = 1; return 0; }
163 // check for edit range specs
164 if( edits.len() > 0 ) {
165 Edit *edit = edits.active(sfrm);
166 if( !edit ) return 0;
168 if( sfrm < (frm=edit->sfrm()) ) sfrm = frm;
169 if( efrm > (frm=edit->efrm()) ) efrm = frm;
170 sofs = edit->ofrm(sfrm);
171 eofs = edit->ofrm(efrm);
175 for( bp=txt; *bp; ++bp )
176 if( !isblank(*bp) && *bp != '|' ) break;
179 for( cp=bp; *cp; ++cp )
180 if( !isblank(*cp) && *cp != '|' ) ep = cp;
184 if( verbose > 2 ) fprintf(stderr,"\r");
185 fprintf(stderr,"%d",sfrm);
186 if( verbose > 1 ) fprintf(stderr,": %*.*s", n, n, bp);
187 fprintf(stderr,"\n");
189 // output txt directly
190 if( ofp && sofs < eofs ) {
191 fprintf(ofp, "{%ld}{%ld}%*.*s\n", sofs, eofs-1, n, n, bp);
193 // last dfrm expired, output edit_data + reset dfrm
194 if( sofs >= deofs ) {
195 if( dlen > 0 ) edit_write();
196 dlen = 0; dsofs = sofs;
198 // append overlapping timeline data
199 if( dlen > 0 && dlen < (int)sizeof(dfrm) ) dfrm[dlen++] = '|';
200 while( bp <= ep && dlen < (int)sizeof(dfrm) ) dfrm[dlen++] = *bp++;
201 if( eofs > deofs ) deofs = eofs;
205 int main(int ac, char *av[])
207 char *cp = 0, *fn = 0;
215 if( --ac <= 0 ) usage();
216 cc_service = atoi(*av++);
219 if( --ac <= 0 ) usage();
220 for( cp=*av++; *cp; ++cp ) {
221 int st = strtol(cp,&cp,0);
222 int len = *cp == ':' ? strtol(cp+1,&cp,0) : INT_MAX;
223 edits.append(st,len);
224 if( *cp != ',' ) break;
226 if( *cp ) { fprintf(stderr,"edit list error at: %s\n",cp); usage(); }
230 if( --ac <= 0 ) usage();
234 if( --ac <= 0 ) usage();
235 verbose = atoi(*av++);
238 if( --ac <= 0 ) usage();
242 if( --ac <= 0 ) usage();
246 if( --ac <= 0 ) usage();
247 wdw_mask = strtoul(*av++,0,0);
249 fprintf(stderr,"no windows in bitmask\n");
258 if( ac > 1 ) usage();
259 if( !access(fn,R_OK) ) break;
260 fprintf(stderr, "no file %s\n", fn);
268 fprintf(stderr,"no output file (-x,-o) in command line arguments\n");
271 if( xfn && ofn && !strcmp(xfn,ofn) ) {
272 fprintf(stderr,"output files (-x,-o) overlap command line arguments\n");
276 if( !strcmp(ofn,"-") ) ofp = stdout;
277 else if( !(ofp=fopen(ofn,"w")) ) {
278 perror(ofn); usage();
282 if( !strcmp(xfn,"-") ) xfp = stdout;
283 else if( !(xfp=fopen(xfn,"w")) ) {
284 perror(xfn); usage();
290 if( !(in = mpeg3_open(fn, &error)) ) {
291 fprintf(stderr, "unable to open %s\n", fn);
294 if( !in->is_transport_stream() ) {
295 fprintf(stderr, "not transport stream %s\n", fn);
298 if( !mpeg3_has_video(in) ) {
299 fprintf(stderr, "no video %s\n", fn);
303 mpeg3_set_cpus(in, 8);
304 int ctrk = cc_service-1;
305 if( ctrk < 0 ) ctrk = 63;
306 mpeg3_show_subtitle(in, vtrk, ctrk);
307 if( mpeg3_set_cc_text_callback(in, vtrk, text_cb) ) {
308 fprintf(stderr, "no video track %d on %s\n", vtrk, fn);
311 if( xfp ) edl_header();
314 while( !done && !mpeg3_read_yuvframe_ptr(in, &yp, &up, &vp, vtrk) )
315 if( verbose > 2 ) fprintf(stderr," \r%ld", mpeg3_get_frame(in, vtrk));
317 if( xfp ) edl_trailer();