add audio to proxy, and minor bug fixes
[goodguy/history.git] / cinelerra-5.1 / libzmpeg3 / video / subtitle.C
1 #include "../libzmpeg3.h"
2
3 zsubtitle_t::
4 subtitle_t()
5 {
6 //zmsgs("subtitle=%p\n",this);
7 }
8
9 // closed caption or display
10 zsubtitle_t::
11 subtitle_t(int nid, int ww, int hh)
12 {
13 //zmsgs("subtitle=%p %dx%d\n", this, ww, hh);
14   id = nid;
15   done = -1;
16   active = -1;
17   draw = -1;
18   set_image_size(ww, hh);
19 }
20
21 zsubtitle_t::
22 ~subtitle_t()
23 {
24 //zmsgs("subtitle=%p/%d subtitle->data=%p %d %d\n", 
25 //  this, id, data, data_allocated, data_used);
26   delete [] data;
27   delete [] image_y;
28   delete [] image_u;
29   delete [] image_v;
30   delete [] image_a;
31 }
32
33 void zsubtitle_t::
34 set_image_size(int isz)
35 {
36 //zmsgs("subtitle=%p/%d\n", this, isz);
37   sz = isz;
38   /* Allocate image buffers */
39   delete [] image_y;
40   delete [] image_u;
41   delete [] image_v;
42   delete [] image_a;
43   image_y = znew(uint8_t,isz);
44   image_u = znew(uint8_t,isz);
45   image_v = znew(uint8_t,isz);
46   image_a = znew(uint8_t,isz);
47 }
48
49 void zsubtitle_t::
50 set_image_size(int ww, int hh)
51 {
52   w = ww;  h = hh;
53   int isz = ww*hh + ww;
54   if( isz > sz ) set_image_size(isz);
55 }
56
57 /* Returns 1 if failure */
58 /*   is_8bit mode has not been tested (no test media) */
59 int zsubtitle_t::
60 decompress_subtitle(zmpeg3_t *zsrc)
61 {
62   //int got_alpha = 0;
63   int is_8bit = 0;
64   uint8_t *yuv_palette = 0;
65   uint8_t *yuv_alpha = 0;
66   int ofsz = 16;
67   bits_t st(zsrc,0);
68   st.use_ptr(data);
69   uint8_t *end = data + data_used;
70   if( st.eos(end,16) ) return 1;
71   int pkt_sz = st.get_bits(16);
72   if( pkt_sz == 0 ) ofsz = 32;
73   int field_offset[3];
74   field_offset[0] = 0; // begining of even field
75   field_offset[1] = 0; // end of even field, begining odd field
76   if( st.eos(end,ofsz) ) return 1;
77   /* end of odd field, beginning of ctl seq */
78   field_offset[2] = st.get_bits(ofsz);
79 //zmsgs("%d 0x%02x%02x data_used=%d data_size=%d\n", 
80 //  __LINE__, data[0],data[1],data_used,field_offset[2]);
81   if( data + field_offset[2] > end ) return 1;
82   palette[0] = 0x00;  palette[1] = 0x01;
83   palette[2] = 0x02;  palette[3] = 0x03;
84   alpha[0]   = 0xff;  alpha[1]   = 0xff;
85   alpha[2]   = 0xff;  alpha[3]   = 0xff;
86   int ww = 0, hh = 0;
87   x1 = 0;  x2 = 0;
88   y1 = 0;  y2 = 0;
89   force = 0;
90   start_time = stop_time = 0;
91
92   /* Advance to control sequences */
93   uint8_t *ptr = data + field_offset[2];
94   uint8_t *last_control_start = 0;
95   uint8_t *next_control_start = ptr;
96
97   while( last_control_start != next_control_start ) {
98     st.use_ptr(next_control_start);
99     if( st.eos(end,16) ) break;  /* date */
100     int date = st.get_bits(16) * 10;
101     /* Offset of next control sequence */
102     if( st.eos(end,ofsz) ) break;
103     int next = st.get_bits(ofsz);
104     last_control_start = next_control_start;
105     next_control_start = data + next;
106     if( next_control_start > end ) return 1;
107
108     int done = 0;
109     while( !done && !st.eos(end,8) ) {
110       int type = st.get_bits(8);
111       switch( type ) {
112         case 0x00:
113           force = 1;
114           break;
115         case 0x01:
116           start_time = date;
117 //zmsgs("start_time %d\n", start_time);
118           break;
119         case 0x02:
120           stop_time = date;
121 //zmsgs("stop_time %d\n", stop_time);
122           break;
123         case 0x83:
124           if( st.eos(end,768*8) ) return 1;
125           yuv_palette = st.input_ptr;
126           st.input_ptr += 768;
127           break;
128         case 0x03:
129           /* Entry in palette of each color */
130           if( st.eos(end,16) ) return 1;
131           for( int i=4; --i>=0; ) palette[i] = st.get_bits(4);
132 //zmsgs("palette %d %d %d %d\n", palette[0], palette[1], palette[2], palette[3]);
133           break;
134         case 0x84:
135           if( st.eos(end,256*8) ) return 1;
136           yuv_alpha = st.input_ptr;
137           st.input_ptr += 256;
138           break;
139         case 0x04:
140           /* Alpha corresponding to each color */
141           if( st.eos(end,16) ) return 1;
142           for( int i=4; --i>=0; ) alpha[i] = st.get_bits(4)*255 / 15;
143           //got_alpha = 1;
144 //zmsgs("alphas %d %d %d %d\n", alpha[0], alpha[1], alpha[2], alpha[3]);
145 #if 0
146           alpha[3] = 0xff; alpha[2] = 0x80;
147           alpha[1] = 0x40; alpha[0] = 0x00;
148 #endif
149           break;
150         case 0x85:
151           is_8bit = 1; // fall thru
152         case 0x05:
153           /* Extent of image on screen */
154           if( st.eos(end,48) ) return 1;
155           x1 = st.get_bits(12) & 0x7ff;
156           x2 = st.get_bits(12) + 1;
157           y1 = st.get_bits(12) & 0x7ff;
158           y2 = st.get_bits(12) + 1;
159           ww = x2 - x1;
160           hh = y2 - y1;
161 //zmsgs("20 x1=%d x2=%d y1=%d y2=%d, %dx%d\n", 
162 //  x1, x2, y1, y2, ww, hh);
163           ww = clip(ww, 1, 2048);  hh = clip(hh, 1, 2048);
164           x1 = clip(x1, 0, 2048);  x2 = clip(x2, 0, 2048);
165           y1 = clip(y1, 0, 2048);  y2 = clip(y2, 0, 2048);
166           break;
167         case 0x86:
168           if( st.eos(end,64) ) return 1;
169           field_offset[0] = st.get_bits(32);
170           field_offset[1] = st.get_bits(32);
171 //zmsgs("offsets even=0x%x odd=0x%x\n", field_offset[0], field_offset[1]);
172           break;
173         case 0x06:
174 /* offsets of even and odd field in compressed data */
175           if( st.eos(end,32) ) return 1;
176           field_offset[0] = st.get_bits(16);
177           field_offset[1] = st.get_bits(16);
178 //zmsgs("offsets even=0x%x odd=0x%x\n", field_offset[0], field_offset[1]);
179           break;
180         case 0xff:
181           done = 1;
182           break;
183         default:
184 //zmsgs("unknown type %02x\n", type);
185           return 1;
186       }
187     }
188   }
189
190   if( ww <= 0 || hh <= 0 || !field_offset[0] ) return 1;
191   if( is_8bit && !yuv_palette ) return 1;
192   set_image_size(ww, hh);
193
194   /* Decode image */
195   int x = 0, y = 0;
196   int field = 0;
197
198   while( field < 2 ) {
199     y = field;
200     ptr = data + field_offset[field++];
201     end = data + field_offset[field];
202     st.use_ptr(ptr);
203     x = 0;
204     while( !st.eos(end) ) {
205       int len, y_color, u_color, v_color, a_color;
206       if( !is_8bit ) {
207         if( st.eos(end,4) ) break;
208         uint32_t zcode = st.get_bits(4);
209         if( zcode < 0x4 ) {
210           if( st.eos(end,4) ) break;
211           zcode = (zcode << 4) | st.get_bits(4);
212           if( zcode < 0x10 ) {
213             if( st.eos(end,4) ) break;
214             zcode = (zcode << 4) | st.get_bits(4);
215             if( zcode < 0x40 ) {
216               if( st.eos(end,4) ) break;
217               zcode = (zcode << 4) | st.get_bits(4);
218               if( zcode < 0x4 ) /* carriage return */
219                 zcode |= (w - x) << 2;
220             }
221           }
222         }
223         int color = (zcode & 0x3);
224         len = zcode >> 2;
225         int n = w - x;
226         if( n < len ) len = n;
227         int k = 4*palette[color];
228         y_color = zsrc->palette[k+0];
229         u_color = zsrc->palette[k+1];
230         v_color = zsrc->palette[k+2];
231         a_color = alpha[color];
232       }
233       else {
234         if( st.eos(end,1) ) break;
235         int has_run = st.get_bits(1);
236         if( st.eos(end,1) ) break;
237         int sz = st.get_bits(1) ? 8 : 2;
238         if( st.eos(end,sz) ) break;
239         int color = st.get_bits(sz);
240         if( has_run ) {
241           if( st.eos(end,1) ) break;
242           if( st.get_bits(1) ) {
243             if( st.eos(end,7) ) break;
244             int n = st.get_bits(7);
245             len = n == 0 ? w - x : n + 9;
246           }
247           else {
248             if( st.eos(end,3) ) break;
249             len = st.get_bits(3) + 2;
250           }
251         }
252         else
253           len = 1;
254         int k = 3*color;
255         y_color = yuv_palette[k+0];
256         u_color = yuv_palette[k+1];
257         v_color = yuv_palette[k+2];
258         a_color = yuv_alpha ? yuv_alpha[color] : 0xff;
259       }
260 //zmsgs("%d, 0x%02x 0x%02x 0x%02x %02x\n",len,y_color,u_color,v_color,a_color);
261       int ofs = y * w + x;
262       memset(image_y+ofs,y_color,len);
263       memset(image_u+ofs,u_color,len);
264       memset(image_v+ofs,v_color,len);
265       memset(image_a+ofs,a_color,len);
266       if( (x+=len) >= w ) {
267         st.next_byte_align();
268         if( (y+=2) >= h ) break;
269         x = 0;
270       }
271     }
272   }
273
274 #if 0
275 /* this code computes a threshold (pass 0),
276  *  and forces pixels below the threshold (pass 1)
277  *  to black and the pixels above to white, as 2x2 yuv macropixels */
278 // Normalize image colors
279   float min_h = 360;
280   float max_h = 0;
281   float threshold = 0;
282 #define HISTOGRAM_SIZE 1000
283 // Decompression coefficients straight out of jpeglib
284 #define V_TO_R    1.40200
285 #define V_TO_G    -0.71414
286
287 #define U_TO_G    -0.34414
288 #define U_TO_B    1.77200
289   uint8_t histogram[HISTOGRAM_SIZE];
290   bzero(histogram, HISTOGRAM_SIZE);
291   for( int pass=0; pass<2; ++pass ) {
292     for( y=0; y<h; ++y ) {
293       for( x=0; x<w; ++x ) {
294         int ofs = y*w + x;
295         if( image_a[ofs]) {
296           uint8_t *y_color = image_y + ofs;
297           uint8_t *a_color = image_a + ofs;
298           uint8_t *u_color = image_u + ofs;
299           uint8_t *v_color = image_v + ofs;
300
301           /* Convert to RGB */
302           float r = (*y_color + *v_color * V_TO_R);
303           float g = (*y_color + *u_color * U_TO_G + *v_color * V_TO_G);
304           float b = (*y_color + *u_color * U_TO_B);
305
306           /* Multiply alpha */
307           /* r = r * *a_color / 0xff; */
308           /* g = g * *a_color / 0xff; */
309           /* b = b * *a_color / 0xff; */
310           /* Convert to HSV */
311           float h, s, v;
312           float min, max, delta;
313           min = ((r < g) ? r : g) < b ? ((r < g) ? r : g) : b;
314           max = ((r > g) ? r : g) > b ? ((r > g) ? r : g) : b;
315           v = max; 
316           delta = max - min;
317           if( max != 0 && delta != 0 ) {
318             s = delta / max;              /* s */
319             if( r == max )
320               h = (g - b) / delta;        /* between yellow & magenta */
321             else if( g == max )
322               h = 2 + (b - r) / delta;    /* between cyan & yellow */
323             else
324               h = 4 + (r - g) / delta;    /* between magenta & cyan */
325
326             h *= 60;                      /* degrees */
327             if( h < 0 ) h += 360;
328           }
329           else {
330             /* r = g = b = 0; */          /* s = 0, v is undefined */
331             s = 0;
332             h = -1;
333           }
334           /* int magnitude = (int)(*y_color * *y_color +  */
335           /*   *u_color * *u_color +  */
336           /*   *v_color * *v_color); */
337
338           /* Multiply alpha */
339           h = (h * *a_color) / 0xff;
340           if( pass == 0 ) {
341             ++histogram[(int)h];
342             if( h < min_h ) min_h = h;
343             if( h > max_h ) max_h = h;
344           }
345           else {
346 // Set new color in a 2x2 pixel block
347             if( h > threshold ) {
348               *y_color = 0xff;
349             }
350             else {
351               *y_color = 0;
352             }
353
354             *u_color = 0x80;
355             *v_color = 0x80;
356             *a_color = 0xff;
357           }
358         }
359       }
360     }
361
362     if( pass == 0 ) {
363       /* int hist_total = 0;                  */
364       /* for( i=0; i<HISTOGRAM_SIZE; ++i )    */
365       /*   hist_total += histogram[i];        */
366       /* int hist_count = 0;                  */
367       /* for( i=0; i<HISTOGRAM_SIZE; ++i ) {  */
368       /*   hist_count += histogram[i];        */
369       /*   if( hist_count > hist_total/3 ) {  */
370       /*     threshold = i;                   */
371       /*     break;                           */
372       /*   }                                  */
373       /* }                                    */
374       threshold = (min_h + max_h) / 2;
375 //    threshold = 324;
376 //zmsgs("min_h=%f max_h=%f threshold=%f\n", min_h, max_h, threshold);
377     }
378   }
379 /* end b/w threshold code */
380 #endif
381
382 //zmsgs("coords: %d,%d - %d,%d size: %d,%d start_time=%d end_time=%d\n", 
383 //  x1, y1, x2, y2, w, h, start_time, stop_time);
384   return 0;
385 }
386
387 void zvideo_t::
388 overlay_subtitle(zsubtitle_t *subtitle)
389 {
390   uint8_t *img_y = subtitle->image_y;
391   uint8_t *img_u = subtitle->image_u;
392   uint8_t *img_v = subtitle->image_v;
393   uint8_t *img_a = subtitle->image_a;
394
395   if( !img_y || !img_u || !img_v || !img_a ) return;
396   int iofs = 0;
397   int x1 = subtitle->x1;
398   if( x1 < 0 ) { iofs += -x1;  x1 = 0; }
399   int x2 = subtitle->x2;
400   if( x2 > coded_picture_width ) x2 = coded_picture_width;
401   int y1 = subtitle->y1;
402   if( y1 < 0 ) { iofs += -y1*subtitle->w;  y1 = 0; }
403   int y2 = subtitle->y2;
404   if( y2 > coded_picture_height ) y2 = coded_picture_height;
405
406   for( int y=y1; y<y2; ++y ) {
407     int oofs = y * coded_picture_width + x1;
408     uint8_t *output_y = subtitle_frame[0] + oofs;
409     oofs = y/2 * chrom_width + x1/2;
410     uint8_t *output_u = subtitle_frame[1] + oofs;
411     uint8_t *output_v = subtitle_frame[2] + oofs;
412     int ofs = iofs + (y-y1) * subtitle->w;
413     uint8_t *input_y = img_y + ofs;
414     uint8_t *input_u = img_u + ofs;
415     uint8_t *input_v = img_v + ofs;
416     uint8_t *input_a = img_a + ofs;
417
418     for( int x=x1; x<x2; ++x ) {
419       int opacity = *input_a;
420       int transparency = 0xff - opacity;
421       *output_y = (*input_y*opacity + *output_y*transparency) / 0xff;
422       ++output_y;
423       if( !(y & 1) && !(x & 1) ) {
424         *output_u = (*input_u*opacity + *output_u*transparency) / 0xff;
425         *output_v = (*input_v*opacity + *output_v*transparency) / 0xff;
426         ++output_u;  ++output_v;
427       }
428       ++input_y;  ++input_a;
429       ++input_u;  ++input_v;
430     }
431   }
432 }
433
434 void zvideo_t::
435 new_output()
436 {
437   int sz = coded_picture_width * coded_picture_height;
438   int isz = chrom_width * chrom_height;
439   if( !subtitle_frame[0] ) {
440     subtitle_frame[0] = new uint8_t[sz+8];
441     subtitle_frame[1] = new uint8_t[isz+8];
442     subtitle_frame[2] = new uint8_t[isz+8];
443   }
444
445   memcpy(subtitle_frame[0], output_src[0], sz);
446   memcpy(subtitle_frame[1], output_src[1], isz);
447   memcpy(subtitle_frame[2], output_src[2], isz);
448
449   output_src[0] = subtitle_frame[0];
450   output_src[1] = subtitle_frame[1];
451   output_src[2] = subtitle_frame[2];
452 }
453
454 int zsubtitle_t::
455 decode(video_t *video)
456 {
457 //zmsgs("id=%d strk=%d i=%d start=%f stop=%f active=%d draw=%d framenow=%f\n",
458 // subtitle->id,strk,i,subtitle->start_frametime,subtitle->stop_frametime,
459 // subtitle->active,subtitle->draw,frame_now);
460   double framerate = video->frame_rate;
461   if( !framerate ) framerate = 30000./1001;
462   if( !active ) {
463     active = 1;
464     if( decompress_subtitle(video->src) ) return -1;
465     int start_frms = framerate * start_time/1000.;
466     int stop_frms = framerate * stop_time/1000.;
467     start_frame = video->framenum + start_frms;
468     stop_frame = video->framenum + stop_frms;
469     frame_time = video->frame_time;
470   }
471   int life_time = video->frame_time - frame_time;
472   if( life_time > 20*framerate ) return -1; // doesn't live forever
473   if( draw < 0 ) return 0;  // never draw
474   if( draw || force > 0 ) return 1;  // always draw
475   if( video->seek_time > 2 ) {
476     /* at least 2 consecutive frames shown since last seek */
477     int hold_frames = framerate * SUBTITLE_HOLD_TIME;
478     int early_frame = start_frame-hold_frames;
479     if( video->framenum < early_frame ) return -1; // way too early
480     int late_frame = stop_frame+hold_frames;
481     if( video->framenum > late_frame ) return -1; // way too late
482   }
483   if( video->framenum < start_frame ) return 0; // too early
484   if( video->framenum >= stop_frame ) return -1;  // too late
485   return 1;
486 }
487
488 void zvideo_t::
489 decode_subtitle()
490 {
491   if( !output_src[0] ) return;
492   int copied = 0;
493   for( int strk=0; strk<src->subtitle_tracks(); ++strk ) {
494     strack_t *strack = src->strack[strk];
495     if( !strack ) continue;
496     if( strack->video && strack->video != this ) continue;
497     strack->rwlock.enter();
498     int i = 0;
499     while( i < strack->total_subtitles ) {
500       subtitle_t *subtitle = strack->subtitles[i];
501       int ret = -1;
502       if( strack->id == subtitle_track || subtitle->force ) {
503         if( (ret=subtitle->decode(this)) > 0 ) {
504           if( !copied ) { copied = 1; new_output(); }
505           overlay_subtitle(subtitle);
506         }
507       }
508       if( ret < 0 ) {
509         strack->del_subtitle(subtitle, -1);
510         if( subtitle->force < 0 ) delete subtitle;
511         continue;
512       }
513       ++i;
514     }
515     strack->rwlock.leave();
516   }
517 }
518
519 int zmpeg3_t::
520 display_subtitle(int stream, int sid, int id,
521    uint8_t *yp, uint8_t *up, uint8_t *vp, uint8_t *ap,
522    int x, int y, int w, int h, double start_msecs, double stop_msecs)
523 {
524   int ret = 1;
525   if( stream >= 0 && stream < total_vtracks ) {
526     vtrack_t *vtrk = vtrack[stream];
527     video_t *video = vtrk->video;
528     strack_t *strack = create_strack(sid, video);
529     strack->rwlock.write_enter();
530     subtitle_t *subtitle = 0;
531     for( int i=strack->total_subtitles; --i>=0 && !subtitle; ) {
532       subtitle_t *sp = strack->subtitles[i];
533       if( sp->id == id ) subtitle = sp;
534     }
535     if( !subtitle ) {
536       subtitle = new subtitle_t(id, w, h);
537       if( strack->append_subtitle(subtitle,0) ) {
538         delete subtitle; subtitle = 0;
539       }
540     }
541     else
542       subtitle->set_image_size(w, h);
543     if( subtitle ) {
544       subtitle->x1 = x;  subtitle->x2 = x + w;
545       subtitle->y1 = y;  subtitle->y2 = y + h;
546       int sz = w * h;
547       if( yp ) memcpy(subtitle->image_y, yp, sz);
548       else memset(subtitle->image_y, 0xff, sz);
549       if( up ) memcpy(subtitle->image_u, up, sz);
550       else memset(subtitle->image_u, 0x80, sz);
551       if( vp ) memcpy(subtitle->image_v, vp, sz);
552       else memset(subtitle->image_v, 0x80, sz);
553       if( ap ) memcpy(subtitle->image_a, ap, sz);
554       else memset(subtitle->image_a, 0xff, sz);
555       subtitle->start_time = start_msecs;
556       subtitle->stop_time = stop_msecs;
557       double framerate = vtrk->frame_rate;
558       if( !framerate ) framerate = 30000./1001;
559       int start_frms = framerate * start_msecs/1000.;
560       int stop_frms = framerate * stop_msecs/1000.;
561       subtitle->start_frame = video->framenum + start_frms;
562       if( stop_msecs ) {
563         subtitle->stop_frame = video->framenum + stop_frms;
564         subtitle->frame_time = video->frame_time;
565       }
566       else // lives forever
567         subtitle->frame_time = subtitle->stop_frame = INT_MAX;
568       subtitle->force = -1;
569       subtitle->draw = 0;
570       ret = 0;
571     }
572     strack->rwlock.write_leave();
573   }
574   return ret;
575 }
576
577 int zmpeg3_t::
578 delete_subtitle(int stream, int sid, int id)
579 {
580   int result = 1;
581   if( stream >= 0 && stream < total_vtracks ) {
582     vtrack_t *vtrk = vtrack[stream];
583     video_t *vid = vtrk->video;
584     strack_t *strack = get_strack_id(sid, vid);
585     if( strack != 0 ) {
586       strack->rwlock.write_enter();
587       for( int i=strack->total_subtitles; --i>=0; ) {
588         subtitle_t *sp = strack->subtitles[i];
589         if( sp->id == id ) {
590           strack->del_subtitle(i);
591           if( sp->force < 0 ) delete sp;
592           result = 0;
593           break;
594         }
595       }
596       strack->rwlock.write_leave();
597     }
598   }
599   return result;
600 }
601