1 #include "mpeg3private.h"
2 #include "mpeg3protos.h"
6 static unsigned char get_nibble(unsigned char **ptr
, int *nibble
)
11 return (*(*ptr
)++) & 0xf;
16 return (*(*ptr
)) >> 4;
20 /* Returns 1 if failure */
21 /* This is largely from spudec, ffmpeg */
22 int decompress_subtitle(mpeg3_t
*file
, mpeg3_subtitle_t
*subtitle
)
25 unsigned char *ptr
= subtitle
->data
;
26 unsigned char *end
= subtitle
->data
+ subtitle
->size
;
33 /* data packet size */
34 if(ptr
+ 2 > end
) return 1;
36 int data_size
= (*ptr
++) << 8;
39 unsigned char *data_start
= ptr
;
40 if(ptr
+ data_size
> end
) return 1;
42 /* Advance to control sequences */
45 subtitle
->palette
[0] = 0x00;
46 subtitle
->palette
[1] = 0x01;
47 subtitle
->palette
[2] = 0x02;
48 subtitle
->palette
[3] = 0x03;
50 subtitle
->alpha
[0] = 0xff;
51 subtitle
->alpha
[1] = 0x00;
52 subtitle
->alpha
[2] = 0x40;
53 subtitle
->alpha
[3] = 0xc0;
55 /* Control sequence */
56 unsigned char *control_start
= 0;
57 unsigned char *next_control_start
= ptr
;
59 while(ptr
< end
&& control_start
!= next_control_start
)
61 control_start
= next_control_start
;
64 if(ptr
+ 2 > end
) break;
65 int date
= (*ptr
++) << 8;
68 /* Offset of next control sequence */
69 if(ptr
+ 2 > end
) break;
70 int next
= (*ptr
++) << 8;
73 next_control_start
= subtitle
->data
+ next
;
76 while(ptr
< end
&& !done
)
87 subtitle
->start_time
= date
;
88 //printf("decompress_subtitle %d\n", subtitle->start_time);
92 subtitle
->stop_time
= date
;
96 /* Entry in palette of each color */
97 if(ptr
+ 4 > end
) return 1;
98 subtitle
->palette
[0] = (*ptr
) >> 4;
99 subtitle
->palette
[1] = (*ptr
++) & 0xf;
100 subtitle
->palette
[2] = (*ptr
) >> 4;
101 subtitle
->palette
[3] = (*ptr
++) & 0xf;
102 //printf("subtitle palette %d %d %d %d\n", subtitle->palette[0], subtitle->palette[1], subtitle->palette[2], subtitle->palette[3]);
106 /* Alpha corresponding to each color */
107 if(ptr
+ 4 > end
) return 1;
108 subtitle
->alpha
[0] = ((*ptr
) >> 4) * 255 / 15;
109 subtitle
->alpha
[1] = ((*ptr
) & 0xf) * 255 / 15;
110 subtitle
->alpha
[2] = ((*ptr
++) >> 4) * 255 / 15;
111 subtitle
->alpha
[3] = ((*ptr
++) & 0xf) * 255 / 15;
113 //printf("subtitle alpha %d %d %d %d\n", subtitle->alpha[0], subtitle->alpha[1], subtitle->alpha[2], subtitle->alpha[3]);
117 /* Extent of image on screen */
118 if(ptr
+ 6 > end
) return 1;
120 * printf("decompress_subtitle 10 %02x %02x %02x %02x %02x %02x\n",
128 subtitle
->x1
= (*ptr
++) << 4;
129 subtitle
->x1
|= (*ptr
) >> 4;
130 subtitle
->x2
= ((*ptr
++) & 0xf) << 8;
131 subtitle
->x2
|= *ptr
++;
132 subtitle
->y1
= (*ptr
++) << 4;
133 subtitle
->y1
|= (*ptr
) >> 4;
134 subtitle
->y2
= ((*ptr
++) & 0xf) << 8;
135 subtitle
->y2
|= *ptr
++;
138 subtitle
->w
= subtitle
->x2
- subtitle
->x1
;
139 subtitle
->h
= subtitle
->y2
- subtitle
->y1
;
141 * printf("decompress_subtitle 20 x1=%d x2=%d y1=%d y2=%d\n",
147 CLAMP(subtitle
->w
, 1, 2048);
148 CLAMP(subtitle
->h
, 1, 2048);
149 CLAMP(subtitle
->x1
, 0, 2048);
150 CLAMP(subtitle
->x2
, 0, 2048);
151 CLAMP(subtitle
->y1
, 0, 2048);
152 CLAMP(subtitle
->y2
, 0, 2048);
156 /* offsets of even and odd field in compressed data */
157 if(ptr
+ 4 > end
) return 1;
158 even_offset
= (ptr
[0] << 8) | (ptr
[1]);
159 odd_offset
= (ptr
[2] << 8) | (ptr
[3]);
160 //printf("decompress_subtitle 30 even=0x%x odd=0x%x\n", even_offset, odd_offset);
169 // printf("unknown type %02x\n", type);
178 /* Allocate image buffer */
179 subtitle
->image_y
= (unsigned char*)calloc(1, subtitle
->w
* subtitle
->h
+ subtitle
->w
);
180 subtitle
->image_u
= (unsigned char*)calloc(1, subtitle
->w
* subtitle
->h
/ 4 + subtitle
->w
);
181 subtitle
->image_v
= (unsigned char*)calloc(1, subtitle
->w
* subtitle
->h
/ 4 + subtitle
->w
);
182 subtitle
->image_a
= (unsigned char*)calloc(1, subtitle
->w
* subtitle
->h
+ subtitle
->w
);
185 int current_nibble
= 0;
186 int x
= 0, y
= 0, field
= 0;
190 while(ptr
< end
&& y
< subtitle
->h
+ 1 && x
< subtitle
->w
)
192 // Start new field based on offset, not total lines
193 if(ptr
- data_start
>= odd_offset
- 4 &&
208 unsigned int code
= get_nibble(&ptr
, ¤t_nibble
);
209 if(code
< 0x4 && ptr
< end
)
211 code
= (code
<< 4) | get_nibble(&ptr
, ¤t_nibble
);
212 if(code
< 0x10 && ptr
< end
)
214 code
= (code
<< 4) | get_nibble(&ptr
, ¤t_nibble
);
215 if(code
< 0x40 && ptr
< end
)
217 code
= (code
<< 4) | get_nibble(&ptr
, ¤t_nibble
);
218 /* carriage return */
219 if(code
< 0x4 && ptr
< end
)
220 code
|= (subtitle
->w
- x
) << 2;
225 int color
= (code
& 0x3);
227 if(len
> subtitle
->w
- x
)
228 len
= subtitle
->w
- x
;
230 int y_color
= file
->palette
[subtitle
->palette
[color
] * 4];
231 int u_color
= file
->palette
[subtitle
->palette
[color
] * 4 + 1];
232 int v_color
= file
->palette
[subtitle
->palette
[color
] * 4 + 2];
233 int a_color
= subtitle
->alpha
[color
];
235 // The alpha seems to be arbitrary. Assume the top left pixel is always
239 subtitle
->alpha
[color
] = 0x0;
245 * printf("0x%02x 0x%02x 0x%02x\n",
252 for(i
= 0; i
< len
; i
++)
254 subtitle
->image_y
[y
* subtitle
->w
+ x
] = y_color
;
255 if(!(x
% 2) && !(y
% 2))
257 subtitle
->image_u
[y
/ 2 * subtitle
->w
/ 2 + x
/ 2] = u_color
;
258 subtitle
->image_v
[y
/ 2 * subtitle
->w
/ 2 + x
/ 2] = v_color
;
260 subtitle
->image_a
[y
* subtitle
->w
+ x
] = a_color
;
277 // Start new field based on total lines, not offset
293 * printf("decompress_subtitle coords: %d,%d - %d,%d size: %d,%d start_time=%d end_time=%d\n",
300 * subtitle->start_time,
301 * subtitle->stop_time);
309 void overlay_subtitle(mpeg3video_t
*video
, mpeg3_subtitle_t
*subtitle
)
312 for(y
= subtitle
->y1
;
313 y
< subtitle
->y2
&& y
< video
->coded_picture_height
;
316 unsigned char *output_y
= video
->subtitle_frame
[0] +
317 y
* video
->coded_picture_width
+
319 unsigned char *output_u
= video
->subtitle_frame
[1] +
320 y
/ 2 * video
->chrom_width
+
322 unsigned char *output_v
= video
->subtitle_frame
[2] +
323 y
/ 2 * video
->chrom_width
+
325 unsigned char *input_y
= subtitle
->image_y
+ (y
- subtitle
->y1
) * subtitle
->w
;
326 unsigned char *input_u
= subtitle
->image_u
+ (y
- subtitle
->y1
) / 2 * subtitle
->w
/ 2;
327 unsigned char *input_v
= subtitle
->image_v
+ (y
- subtitle
->y1
) / 2 * subtitle
->w
/ 2;
328 unsigned char *input_a
= subtitle
->image_a
+ (y
- subtitle
->y1
) * subtitle
->w
;
330 for(x
= subtitle
->x1
;
331 x
< subtitle
->x2
&& x
< video
->coded_picture_width
;
334 int opacity
= *input_a
;
335 int transparency
= 0xff - opacity
;
336 *output_y
= (*input_y
* opacity
+ *output_y
* transparency
) / 0xff;
338 if(!(y
% 2) && !(x
% 2))
340 *output_u
= (*input_u
* opacity
+ *output_u
* transparency
) / 0xff;
341 *output_v
= (*input_v
* opacity
+ *output_v
* transparency
) / 0xff;
357 void mpeg3_decode_subtitle(mpeg3video_t
*video
)
359 /* Test demuxer for subtitle */
360 mpeg3_vtrack_t
*vtrack
= (mpeg3_vtrack_t
*)video
->track
;
361 mpeg3_t
*file
= (mpeg3_t
*)video
->file
;
363 /* Clear subtitles from inactive subtitle tracks */
365 for(i
= 0; i
< mpeg3_subtitle_tracks(file
); i
++)
367 if(i
!= file
->subtitle_track
)
368 mpeg3_pop_all_subtitles(mpeg3_get_strack(file
, i
));
371 if(file
->subtitle_track
>= 0 &&
372 file
->subtitle_track
< mpeg3_subtitle_tracks(file
))
374 mpeg3_strack_t
*strack
= mpeg3_get_strack(file
, file
->subtitle_track
);
378 for(i
= 0; i
< strack
->total_subtitles
; i
++)
380 mpeg3_subtitle_t
*subtitle
= strack
->subtitles
[i
];
381 if(!subtitle
->active
)
383 /* Exclude object from future activation */
384 subtitle
->active
= 1;
386 /* Decompress subtitle */
387 if(decompress_subtitle(file
, subtitle
))
389 /* Remove subtitle if failed */
390 mpeg3_pop_subtitle(strack
, i
, 1);
398 /* Test start and end time of subtitle */
399 if(subtitle
->stop_time
> 0)
401 /* Copy video to temporary */
404 if(!video
->subtitle_frame
[0])
406 video
->subtitle_frame
[0] = malloc(
407 video
->coded_picture_width
*
408 video
->coded_picture_height
+ 8);
409 video
->subtitle_frame
[1] = malloc(
411 video
->chrom_height
+ 8);
412 video
->subtitle_frame
[2] = malloc(
414 video
->chrom_height
+ 8);
417 memcpy(video
->subtitle_frame
[0],
418 video
->output_src
[0],
419 video
->coded_picture_width
* video
->coded_picture_height
);
420 memcpy(video
->subtitle_frame
[1],
421 video
->output_src
[1],
422 video
->chrom_width
* video
->chrom_height
);
423 memcpy(video
->subtitle_frame
[2],
424 video
->output_src
[2],
425 video
->chrom_width
* video
->chrom_height
);
427 video
->output_src
[0] = video
->subtitle_frame
[0];
428 video
->output_src
[1] = video
->subtitle_frame
[1];
429 video
->output_src
[2] = video
->subtitle_frame
[2];
434 /* Overlay subtitle on video */
435 overlay_subtitle(video
, subtitle
);
436 subtitle
->stop_time
-= (int)(100.0 / video
->frame_rate
);
439 if(subtitle
->stop_time
<= 0)
441 mpeg3_pop_subtitle(strack
, i
, 1);