1 #include "../libzmpeg3.h"
6 //zmsgs("subtitle=%p\n",this);
9 // closed caption or display
11 subtitle_t(int nid, int ww, int hh)
13 //zmsgs("subtitle=%p %dx%d\n", this, ww, hh);
18 set_image_size(ww, hh);
24 //zmsgs("subtitle=%p/%d subtitle->data=%p %d %d\n",
25 // this, id, data, data_allocated, data_used);
34 set_image_size(int isz)
36 //zmsgs("subtitle=%p/%d\n", this, isz);
38 /* Allocate image buffers */
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);
50 set_image_size(int ww, int hh)
54 if( isz > sz ) set_image_size(isz);
57 /* Returns 1 if failure */
58 /* is_8bit mode has not been tested (no test media) */
60 decompress_subtitle(zmpeg3_t *zsrc)
64 uint8_t *yuv_palette = 0;
65 uint8_t *yuv_alpha = 0;
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;
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;
90 start_time = stop_time = 0;
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;
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;
109 while( !done && !st.eos(end,8) ) {
110 int type = st.get_bits(8);
117 //zmsgs("start_time %d\n", start_time);
121 //zmsgs("stop_time %d\n", stop_time);
124 if( st.eos(end,768*8) ) return 1;
125 yuv_palette = st.input_ptr;
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]);
135 if( st.eos(end,256*8) ) return 1;
136 yuv_alpha = st.input_ptr;
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;
144 //zmsgs("alphas %d %d %d %d\n", alpha[0], alpha[1], alpha[2], alpha[3]);
146 alpha[3] = 0xff; alpha[2] = 0x80;
147 alpha[1] = 0x40; alpha[0] = 0x00;
151 is_8bit = 1; // fall thru
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;
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);
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]);
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]);
184 //zmsgs("unknown type %02x\n", type);
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);
200 ptr = data + field_offset[field++];
201 end = data + field_offset[field];
204 while( !st.eos(end) ) {
205 int len, y_color, u_color, v_color, a_color;
207 if( st.eos(end,4) ) break;
208 uint32_t zcode = st.get_bits(4);
210 if( st.eos(end,4) ) break;
211 zcode = (zcode << 4) | st.get_bits(4);
213 if( st.eos(end,4) ) break;
214 zcode = (zcode << 4) | st.get_bits(4);
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;
223 int color = (zcode & 0x3);
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];
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);
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;
248 if( st.eos(end,3) ) break;
249 len = st.get_bits(3) + 2;
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;
260 //zmsgs("%d, 0x%02x 0x%02x 0x%02x %02x\n",len,y_color,u_color,v_color,a_color);
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;
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
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
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 ) {
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;
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);
307 /* r = r * *a_color / 0xff; */
308 /* g = g * *a_color / 0xff; */
309 /* b = b * *a_color / 0xff; */
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;
317 if( max != 0 && delta != 0 ) {
318 s = delta / max; /* s */
320 h = (g - b) / delta; /* between yellow & magenta */
322 h = 2 + (b - r) / delta; /* between cyan & yellow */
324 h = 4 + (r - g) / delta; /* between magenta & cyan */
326 h *= 60; /* degrees */
327 if( h < 0 ) h += 360;
330 /* r = g = b = 0; */ /* s = 0, v is undefined */
334 /* int magnitude = (int)(*y_color * *y_color + */
335 /* *u_color * *u_color + */
336 /* *v_color * *v_color); */
339 h = (h * *a_color) / 0xff;
342 if( h < min_h ) min_h = h;
343 if( h > max_h ) max_h = h;
346 // Set new color in a 2x2 pixel block
347 if( h > threshold ) {
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 ) { */
374 threshold = (min_h + max_h) / 2;
376 //zmsgs("min_h=%f max_h=%f threshold=%f\n", min_h, max_h, threshold);
379 /* end b/w threshold code */
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);
388 overlay_subtitle(zsubtitle_t *subtitle)
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;
395 if( !img_y || !img_u || !img_v || !img_a ) return;
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;
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;
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;
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;
428 ++input_y; ++input_a;
429 ++input_u; ++input_v;
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];
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);
449 output_src[0] = subtitle_frame[0];
450 output_src[1] = subtitle_frame[1];
451 output_src[2] = subtitle_frame[2];
455 decode(video_t *video)
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;
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;
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
483 if( video->framenum < start_frame ) return 0; // too early
484 if( video->framenum >= stop_frame ) return -1; // too late
491 if( !output_src[0] ) return;
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();
499 while( i < strack->total_subtitles ) {
500 subtitle_t *subtitle = strack->subtitles[i];
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);
509 strack->del_subtitle(subtitle, -1);
510 if( subtitle->force < 0 ) delete subtitle;
515 strack->rwlock.leave();
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)
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;
536 subtitle = new subtitle_t(id, w, h);
537 if( strack->append_subtitle(subtitle,0) ) {
538 delete subtitle; subtitle = 0;
542 subtitle->set_image_size(w, h);
544 subtitle->x1 = x; subtitle->x2 = x + w;
545 subtitle->y1 = y; subtitle->y2 = y + 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;
563 subtitle->stop_frame = video->framenum + stop_frms;
564 subtitle->frame_time = video->frame_time;
566 else // lives forever
567 subtitle->frame_time = subtitle->stop_frame = INT_MAX;
568 subtitle->force = -1;
572 strack->rwlock.write_leave();
578 delete_subtitle(int stream, int sid, int id)
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);
586 strack->rwlock.write_enter();
587 for( int i=strack->total_subtitles; --i>=0; ) {
588 subtitle_t *sp = strack->subtitles[i];
590 strack->del_subtitle(i);
591 if( sp->force < 0 ) delete sp;
596 strack->rwlock.write_leave();