00001 #include "mpeg3private.h"
00002 #include "mpeg3protos.h"
00003
00004 #include <stdlib.h>
00005
00006 static unsigned char get_nibble(unsigned char **ptr, int *nibble)
00007 {
00008 if(*nibble)
00009 {
00010 *nibble = !*nibble;
00011 return (*(*ptr)++) & 0xf;
00012 }
00013 else
00014 {
00015 *nibble = !*nibble;
00016 return (*(*ptr)) >> 4;
00017 }
00018 }
00019
00020
00021
00022 int decompress_subtitle(mpeg3_t *file, mpeg3_subtitle_t *subtitle)
00023 {
00024 int i;
00025 unsigned char *ptr = subtitle->data;
00026 unsigned char *end = subtitle->data + subtitle->size;
00027 int even_offset = 0;
00028 int odd_offset = 0;
00029
00030
00031 ptr += 2;
00032
00033
00034 if(ptr + 2 > end) return 1;
00035
00036 int data_size = (*ptr++) << 8;
00037 data_size |= *ptr++;
00038
00039 unsigned char *data_start = ptr;
00040 if(ptr + data_size > end) return 1;
00041
00042
00043 ptr += data_size - 2;
00044
00045 subtitle->palette[0] = 0x00;
00046 subtitle->palette[1] = 0x01;
00047 subtitle->palette[2] = 0x02;
00048 subtitle->palette[3] = 0x03;
00049
00050 subtitle->alpha[0] = 0xff;
00051 subtitle->alpha[1] = 0x00;
00052 subtitle->alpha[2] = 0x40;
00053 subtitle->alpha[3] = 0xc0;
00054
00055
00056 unsigned char *control_start = 0;
00057 unsigned char *next_control_start = ptr;
00058 int got_alpha = 0;
00059 while(ptr < end && control_start != next_control_start)
00060 {
00061 control_start = next_control_start;
00062
00063
00064 if(ptr + 2 > end) break;
00065 int date = (*ptr++) << 8;
00066 date |= *ptr++;
00067
00068
00069 if(ptr + 2 > end) break;
00070 int next = (*ptr++) << 8;
00071 next |= *ptr++;
00072
00073 next_control_start = subtitle->data + next;
00074
00075 int done = 0;
00076 while(ptr < end && !done)
00077 {
00078 int type = *ptr++;
00079
00080 switch(type)
00081 {
00082 case 0x00:
00083 subtitle->force = 1;
00084 break;
00085
00086 case 0x01:
00087 subtitle->start_time = date;
00088
00089 break;
00090
00091 case 0x02:
00092 subtitle->stop_time = date;
00093 break;
00094
00095 case 0x03:
00096
00097 if(ptr + 4 > end) return 1;
00098 subtitle->palette[0] = (*ptr) >> 4;
00099 subtitle->palette[1] = (*ptr++) & 0xf;
00100 subtitle->palette[2] = (*ptr) >> 4;
00101 subtitle->palette[3] = (*ptr++) & 0xf;
00102
00103 break;
00104
00105 case 0x04:
00106
00107 if(ptr + 4 > end) return 1;
00108 subtitle->alpha[0] = ((*ptr) >> 4) * 255 / 15;
00109 subtitle->alpha[1] = ((*ptr) & 0xf) * 255 / 15;
00110 subtitle->alpha[2] = ((*ptr++) >> 4) * 255 / 15;
00111 subtitle->alpha[3] = ((*ptr++) & 0xf) * 255 / 15;
00112 got_alpha = 1;
00113
00114 break;
00115
00116 case 0x05:
00117
00118 if(ptr + 6 > end) return 1;
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128 subtitle->x1 = (*ptr++) << 4;
00129 subtitle->x1 |= (*ptr) >> 4;
00130 subtitle->x2 = ((*ptr++) & 0xf) << 8;
00131 subtitle->x2 |= *ptr++;
00132 subtitle->y1 = (*ptr++) << 4;
00133 subtitle->y1 |= (*ptr) >> 4;
00134 subtitle->y2 = ((*ptr++) & 0xf) << 8;
00135 subtitle->y2 |= *ptr++;
00136 subtitle->x2++;
00137 subtitle->y2++;
00138 subtitle->w = subtitle->x2 - subtitle->x1;
00139 subtitle->h = subtitle->y2 - subtitle->y1;
00140
00141
00142
00143
00144
00145
00146
00147 CLAMP(subtitle->w, 1, 2048);
00148 CLAMP(subtitle->h, 1, 2048);
00149 CLAMP(subtitle->x1, 0, 2048);
00150 CLAMP(subtitle->x2, 0, 2048);
00151 CLAMP(subtitle->y1, 0, 2048);
00152 CLAMP(subtitle->y2, 0, 2048);
00153 break;
00154
00155 case 0x06:
00156
00157 if(ptr + 4 > end) return 1;
00158 even_offset = (ptr[0] << 8) | (ptr[1]);
00159 odd_offset = (ptr[2] << 8) | (ptr[3]);
00160
00161 ptr += 4;
00162 break;
00163
00164 case 0xff:
00165 done = 1;
00166 break;
00167
00168 default:
00169
00170 break;
00171 }
00172 }
00173
00174 }
00175
00176
00177
00178
00179 subtitle->image_y = (unsigned char*)calloc(1, subtitle->w * subtitle->h + subtitle->w);
00180 subtitle->image_u = (unsigned char*)calloc(1, subtitle->w * subtitle->h / 4 + subtitle->w);
00181 subtitle->image_v = (unsigned char*)calloc(1, subtitle->w * subtitle->h / 4 + subtitle->w);
00182 subtitle->image_a = (unsigned char*)calloc(1, subtitle->w * subtitle->h + subtitle->w);
00183
00184
00185 int current_nibble = 0;
00186 int x = 0, y = 0, field = 0;
00187 ptr = data_start;
00188 int first_pixel = 1;
00189
00190 while(ptr < end && y < subtitle->h + 1 && x < subtitle->w)
00191 {
00192
00193 if(ptr - data_start >= odd_offset - 4 &&
00194 field == 0)
00195 {
00196 field = 1;
00197 y = 1;
00198 x = 0;
00199
00200 if(current_nibble)
00201 {
00202 ptr++;
00203 current_nibble = 0;
00204 }
00205 }
00206
00207
00208 unsigned int code = get_nibble(&ptr, ¤t_nibble);
00209 if(code < 0x4 && ptr < end)
00210 {
00211 code = (code << 4) | get_nibble(&ptr, ¤t_nibble);
00212 if(code < 0x10 && ptr < end)
00213 {
00214 code = (code << 4) | get_nibble(&ptr, ¤t_nibble);
00215 if(code < 0x40 && ptr < end)
00216 {
00217 code = (code << 4) | get_nibble(&ptr, ¤t_nibble);
00218
00219 if(code < 0x4 && ptr < end)
00220 code |= (subtitle->w - x) << 2;
00221 }
00222 }
00223 }
00224
00225 int color = (code & 0x3);
00226 int len = code >> 2;
00227 if(len > subtitle->w - x)
00228 len = subtitle->w - x;
00229
00230 int y_color = file->palette[subtitle->palette[color] * 4];
00231 int u_color = file->palette[subtitle->palette[color] * 4 + 1];
00232 int v_color = file->palette[subtitle->palette[color] * 4 + 2];
00233 int a_color = subtitle->alpha[color];
00234
00235
00236
00237 if(first_pixel)
00238 {
00239 subtitle->alpha[color] = 0x0;
00240 a_color = 0x0;
00241 first_pixel = 0;
00242 }
00243
00244
00245
00246
00247
00248
00249
00250 if(y < subtitle->h)
00251 {
00252 for(i = 0; i < len; i++)
00253 {
00254 subtitle->image_y[y * subtitle->w + x] = y_color;
00255 if(!(x % 2) && !(y % 2))
00256 {
00257 subtitle->image_u[y / 2 * subtitle->w / 2 + x / 2] = u_color;
00258 subtitle->image_v[y / 2 * subtitle->w / 2 + x / 2] = v_color;
00259 }
00260 subtitle->image_a[y * subtitle->w + x] = a_color;
00261 x++;
00262 }
00263 }
00264
00265 if(x >= subtitle->w)
00266 {
00267 x = 0;
00268 y += 2;
00269
00270
00271 if(current_nibble)
00272 {
00273 ptr++;
00274 current_nibble = 0;
00275 }
00276
00277
00278 if(y >= subtitle->h)
00279 {
00280 y = subtitle->h - 1;
00281
00282
00283
00284
00285
00286
00287
00288 }
00289 }
00290 }
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303 return 0;
00304 }
00305
00306
00307
00308
00309 void overlay_subtitle(mpeg3video_t *video, mpeg3_subtitle_t *subtitle)
00310 {
00311 int x, y;
00312 for(y = subtitle->y1;
00313 y < subtitle->y2 && y < video->coded_picture_height;
00314 y++)
00315 {
00316 unsigned char *output_y = video->subtitle_frame[0] +
00317 y * video->coded_picture_width +
00318 subtitle->x1;
00319 unsigned char *output_u = video->subtitle_frame[1] +
00320 y / 2 * video->chrom_width +
00321 subtitle->x1 / 2;
00322 unsigned char *output_v = video->subtitle_frame[2] +
00323 y / 2 * video->chrom_width +
00324 subtitle->x1 / 2;
00325 unsigned char *input_y = subtitle->image_y + (y - subtitle->y1) * subtitle->w;
00326 unsigned char *input_u = subtitle->image_u + (y - subtitle->y1) / 2 * subtitle->w / 2;
00327 unsigned char *input_v = subtitle->image_v + (y - subtitle->y1) / 2 * subtitle->w / 2;
00328 unsigned char *input_a = subtitle->image_a + (y - subtitle->y1) * subtitle->w;
00329
00330 for(x = subtitle->x1;
00331 x < subtitle->x2 && x < video->coded_picture_width;
00332 x++)
00333 {
00334 int opacity = *input_a;
00335 int transparency = 0xff - opacity;
00336 *output_y = (*input_y * opacity + *output_y * transparency) / 0xff;
00337
00338 if(!(y % 2) && !(x % 2))
00339 {
00340 *output_u = (*input_u * opacity + *output_u * transparency) / 0xff;
00341 *output_v = (*input_v * opacity + *output_v * transparency) / 0xff;
00342 output_u++;
00343 output_v++;
00344 input_u++;
00345 input_v++;
00346 }
00347
00348 output_y++;
00349 input_y++;
00350 input_a++;
00351 }
00352 }
00353 }
00354
00355
00356
00357 void mpeg3_decode_subtitle(mpeg3video_t *video)
00358 {
00359
00360 mpeg3_vtrack_t *vtrack = (mpeg3_vtrack_t*)video->track;
00361 mpeg3_t *file = (mpeg3_t*)video->file;
00362
00363
00364 int i;
00365 for(i = 0; i < mpeg3_subtitle_tracks(file); i++)
00366 {
00367 if(i != file->subtitle_track)
00368 mpeg3_pop_all_subtitles(mpeg3_get_strack(file, i));
00369 }
00370
00371 if(file->subtitle_track >= 0 &&
00372 file->subtitle_track < mpeg3_subtitle_tracks(file))
00373 {
00374 mpeg3_strack_t *strack = mpeg3_get_strack(file, file->subtitle_track);
00375 int total = 0;
00376 if(strack)
00377 {
00378 for(i = 0; i < strack->total_subtitles; i++)
00379 {
00380 mpeg3_subtitle_t *subtitle = strack->subtitles[i];
00381 if(!subtitle->active)
00382 {
00383
00384 subtitle->active = 1;
00385
00386
00387 if(decompress_subtitle(file, subtitle))
00388 {
00389
00390 mpeg3_pop_subtitle(strack, i, 1);
00391 i--;
00392 continue;
00393 }
00394 }
00395
00396
00397
00398
00399 if(subtitle->stop_time > 0)
00400 {
00401
00402 if(!total)
00403 {
00404 if(!video->subtitle_frame[0])
00405 {
00406 video->subtitle_frame[0] = malloc(
00407 video->coded_picture_width *
00408 video->coded_picture_height + 8);
00409 video->subtitle_frame[1] = malloc(
00410 video->chrom_width *
00411 video->chrom_height + 8);
00412 video->subtitle_frame[2] = malloc(
00413 video->chrom_width *
00414 video->chrom_height + 8);
00415 }
00416
00417 memcpy(video->subtitle_frame[0],
00418 video->output_src[0],
00419 video->coded_picture_width * video->coded_picture_height);
00420 memcpy(video->subtitle_frame[1],
00421 video->output_src[1],
00422 video->chrom_width * video->chrom_height);
00423 memcpy(video->subtitle_frame[2],
00424 video->output_src[2],
00425 video->chrom_width * video->chrom_height);
00426
00427 video->output_src[0] = video->subtitle_frame[0];
00428 video->output_src[1] = video->subtitle_frame[1];
00429 video->output_src[2] = video->subtitle_frame[2];
00430 }
00431 total++;
00432
00433
00434
00435 overlay_subtitle(video, subtitle);
00436 subtitle->stop_time -= (int)(100.0 / video->frame_rate);
00437 }
00438
00439 if(subtitle->stop_time <= 0)
00440 {
00441 mpeg3_pop_subtitle(strack, i, 1);
00442 i--;
00443 }
00444 }
00445 }
00446 }
00447
00448
00449
00450
00451 }
00452
00453
00454
00455
00456