Fixed initialisation of tf in file_open(). Without setting the memory to 0,
[cinelerra_cv/mob.git] / libmpeg3 / video / subtitle.c
blob0e80f841b5241c87adbcbc7ceaf8618547289eec
1 #include "mpeg3private.h"
2 #include "mpeg3protos.h"
4 #include <stdlib.h>
6 static unsigned char get_nibble(unsigned char **ptr, int *nibble)
8 if(*nibble)
10 *nibble = !*nibble;
11 return (*(*ptr)++) & 0xf;
13 else
15 *nibble = !*nibble;
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)
24 int i;
25 unsigned char *ptr = subtitle->data;
26 unsigned char *end = subtitle->data + subtitle->size;
27 int even_offset = 0;
28 int odd_offset = 0;
30 /* packet size */
31 ptr += 2;
33 /* data packet size */
34 if(ptr + 2 > end) return 1;
36 int data_size = (*ptr++) << 8;
37 data_size |= *ptr++;
39 unsigned char *data_start = ptr;
40 if(ptr + data_size > end) return 1;
42 /* Advance to control sequences */
43 ptr += data_size - 2;
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;
58 int got_alpha = 0;
59 while(ptr < end && control_start != next_control_start)
61 control_start = next_control_start;
63 /* Date */
64 if(ptr + 2 > end) break;
65 int date = (*ptr++) << 8;
66 date |= *ptr++;
68 /* Offset of next control sequence */
69 if(ptr + 2 > end) break;
70 int next = (*ptr++) << 8;
71 next |= *ptr++;
73 next_control_start = subtitle->data + next;
75 int done = 0;
76 while(ptr < end && !done)
78 int type = *ptr++;
80 switch(type)
82 case 0x00:
83 subtitle->force = 1;
84 break;
86 case 0x01:
87 subtitle->start_time = date;
88 //printf("decompress_subtitle %d\n", subtitle->start_time);
89 break;
91 case 0x02:
92 subtitle->stop_time = date;
93 break;
95 case 0x03:
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]);
103 break;
105 case 0x04:
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;
112 got_alpha = 1;
113 //printf("subtitle alpha %d %d %d %d\n", subtitle->alpha[0], subtitle->alpha[1], subtitle->alpha[2], subtitle->alpha[3]);
114 break;
116 case 0x05:
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",
121 * ptr[0],
122 * ptr[1],
123 * ptr[2],
124 * ptr[3],
125 * ptr[4],
126 * ptr[5]);
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++;
136 subtitle->x2++;
137 subtitle->y2++;
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",
142 * subtitle->x1,
143 * subtitle->x2,
144 * subtitle->y1,
145 * subtitle->y2);
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);
153 break;
155 case 0x06:
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);
161 ptr += 4;
162 break;
164 case 0xff:
165 done = 1;
166 break;
168 default:
169 // printf("unknown type %02x\n", type);
170 break;
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);
184 /* Decode image */
185 int current_nibble = 0;
186 int x = 0, y = 0, field = 0;
187 ptr = data_start;
188 int first_pixel = 1;
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 &&
194 field == 0)
196 field = 1;
197 y = 1;
198 x = 0;
200 if(current_nibble)
202 ptr++;
203 current_nibble = 0;
208 unsigned int code = get_nibble(&ptr, &current_nibble);
209 if(code < 0x4 && ptr < end)
211 code = (code << 4) | get_nibble(&ptr, &current_nibble);
212 if(code < 0x10 && ptr < end)
214 code = (code << 4) | get_nibble(&ptr, &current_nibble);
215 if(code < 0x40 && ptr < end)
217 code = (code << 4) | get_nibble(&ptr, &current_nibble);
218 /* carriage return */
219 if(code < 0x4 && ptr < end)
220 code |= (subtitle->w - x) << 2;
225 int color = (code & 0x3);
226 int len = code >> 2;
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
236 // transparent.
237 if(first_pixel)
239 subtitle->alpha[color] = 0x0;
240 a_color = 0x0;
241 first_pixel = 0;
245 * printf("0x%02x 0x%02x 0x%02x\n",
246 * y_color,
247 * u_color,
248 * v_color);
250 if(y < subtitle->h)
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;
261 x++;
265 if(x >= subtitle->w)
267 x = 0;
268 y += 2;
270 /* Byte alignment */
271 if(current_nibble)
273 ptr++;
274 current_nibble = 0;
277 // Start new field based on total lines, not offset
278 if(y >= subtitle->h)
280 y = subtitle->h - 1;
282 * if(!field)
284 * y = 1;
285 * field = 1;
293 * printf("decompress_subtitle coords: %d,%d - %d,%d size: %d,%d start_time=%d end_time=%d\n",
294 * subtitle->x1,
295 * subtitle->y1,
296 * subtitle->x2,
297 * subtitle->y2,
298 * subtitle->w,
299 * subtitle->h,
300 * subtitle->start_time,
301 * subtitle->stop_time);
303 return 0;
309 void overlay_subtitle(mpeg3video_t *video, mpeg3_subtitle_t *subtitle)
311 int x, y;
312 for(y = subtitle->y1;
313 y < subtitle->y2 && y < video->coded_picture_height;
314 y++)
316 unsigned char *output_y = video->subtitle_frame[0] +
317 y * video->coded_picture_width +
318 subtitle->x1;
319 unsigned char *output_u = video->subtitle_frame[1] +
320 y / 2 * video->chrom_width +
321 subtitle->x1 / 2;
322 unsigned char *output_v = video->subtitle_frame[2] +
323 y / 2 * video->chrom_width +
324 subtitle->x1 / 2;
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;
332 x++)
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;
342 output_u++;
343 output_v++;
344 input_u++;
345 input_v++;
348 output_y++;
349 input_y++;
350 input_a++;
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 */
364 int i;
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);
375 int total = 0;
376 if(strack)
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);
391 i--;
392 continue;
398 /* Test start and end time of subtitle */
399 if(subtitle->stop_time > 0)
401 /* Copy video to temporary */
402 if(!total)
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(
410 video->chrom_width *
411 video->chrom_height + 8);
412 video->subtitle_frame[2] = malloc(
413 video->chrom_width *
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];
431 total++;
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);
442 i--;