00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00027 #include "avcodec.h"
00028 #include "dsputil.h"
00029 #include "bytestream.h"
00030 #include "libavutil/colorspace.h"
00031 #include "libavutil/imgutils.h"
00032 #include "libavutil/opt.h"
00033
00034 #define RGBA(r,g,b,a) (((a) << 24) | ((r) << 16) | ((g) << 8) | (b))
00035
00036 enum SegmentType {
00037 PALETTE_SEGMENT = 0x14,
00038 PICTURE_SEGMENT = 0x15,
00039 PRESENTATION_SEGMENT = 0x16,
00040 WINDOW_SEGMENT = 0x17,
00041 DISPLAY_SEGMENT = 0x80,
00042 };
00043
00044 typedef struct PGSSubPictureReference {
00045 int x;
00046 int y;
00047 int picture_id;
00048 int composition;
00049 } PGSSubPictureReference;
00050
00051 typedef struct PGSSubPresentation {
00052 int id_number;
00053 int object_count;
00054 PGSSubPictureReference *objects;
00055 } PGSSubPresentation;
00056
00057 typedef struct PGSSubPicture {
00058 int w;
00059 int h;
00060 uint8_t *rle;
00061 unsigned int rle_buffer_size, rle_data_len;
00062 unsigned int rle_remaining_len;
00063 } PGSSubPicture;
00064
00065 typedef struct PGSSubContext {
00066 AVClass *class;
00067 PGSSubPresentation presentation;
00068 uint32_t clut[256];
00069 PGSSubPicture pictures[UINT16_MAX];
00070 int forced_subs_only;
00071 } PGSSubContext;
00072
00073 static av_cold int init_decoder(AVCodecContext *avctx)
00074 {
00075 avctx->pix_fmt = PIX_FMT_PAL8;
00076
00077 return 0;
00078 }
00079
00080 static av_cold int close_decoder(AVCodecContext *avctx)
00081 {
00082 uint16_t picture;
00083
00084 PGSSubContext *ctx = avctx->priv_data;
00085
00086 av_freep(&ctx->presentation.objects);
00087 ctx->presentation.object_count = 0;
00088
00089 for (picture = 0; picture < UINT16_MAX; ++picture) {
00090 av_freep(&ctx->pictures[picture].rle);
00091 ctx->pictures[picture].rle_buffer_size = 0;
00092 }
00093
00094 return 0;
00095 }
00096
00107 static int decode_rle(AVCodecContext *avctx, AVSubtitle *sub, int rect,
00108 const uint8_t *buf, unsigned int buf_size)
00109 {
00110 const uint8_t *rle_bitmap_end;
00111 int pixel_count, line_count;
00112
00113 rle_bitmap_end = buf + buf_size;
00114
00115 sub->rects[rect]->pict.data[0] = av_malloc(sub->rects[rect]->w * sub->rects[rect]->h);
00116
00117 if (!sub->rects[rect]->pict.data[0])
00118 return -1;
00119
00120 pixel_count = 0;
00121 line_count = 0;
00122
00123 while (buf < rle_bitmap_end && line_count < sub->rects[rect]->h) {
00124 uint8_t flags, color;
00125 int run;
00126
00127 color = bytestream_get_byte(&buf);
00128 run = 1;
00129
00130 if (color == 0x00) {
00131 flags = bytestream_get_byte(&buf);
00132 run = flags & 0x3f;
00133 if (flags & 0x40)
00134 run = (run << 8) + bytestream_get_byte(&buf);
00135 color = flags & 0x80 ? bytestream_get_byte(&buf) : 0;
00136 }
00137
00138 if (run > 0 && pixel_count + run <= sub->rects[rect]->w * sub->rects[rect]->h) {
00139 memset(sub->rects[rect]->pict.data[0] + pixel_count, color, run);
00140 pixel_count += run;
00141 } else if (!run) {
00142
00143
00144
00145
00146 if (pixel_count % sub->rects[rect]->w > 0)
00147 av_log(avctx, AV_LOG_ERROR, "Decoded %d pixels, when line should be %d pixels\n",
00148 pixel_count % sub->rects[rect]->w, sub->rects[rect]->w);
00149 line_count++;
00150 }
00151 }
00152
00153 if (pixel_count < sub->rects[rect]->w * sub->rects[rect]->h) {
00154 av_log(avctx, AV_LOG_ERROR, "Insufficient RLE data for subtitle\n");
00155 return -1;
00156 }
00157
00158 av_dlog(avctx, "Pixel Count = %d, Area = %d\n", pixel_count, sub->rects[rect]->w * sub->rects[rect]->h);
00159
00160 return 0;
00161 }
00162
00174 static int parse_picture_segment(AVCodecContext *avctx,
00175 const uint8_t *buf, int buf_size)
00176 {
00177 PGSSubContext *ctx = avctx->priv_data;
00178
00179 uint8_t sequence_desc;
00180 unsigned int rle_bitmap_len, width, height;
00181 uint16_t picture_id;
00182
00183 if (buf_size <= 4)
00184 return -1;
00185 buf_size -= 4;
00186
00187 picture_id = bytestream_get_be16(&buf);
00188
00189
00190 buf++;
00191
00192
00193 sequence_desc = bytestream_get_byte(&buf);
00194
00195 if (!(sequence_desc & 0x80)) {
00196
00197 if (buf_size > ctx->pictures[picture_id].rle_remaining_len)
00198 return -1;
00199
00200 memcpy(ctx->pictures[picture_id].rle + ctx->pictures[picture_id].rle_data_len, buf, buf_size);
00201 ctx->pictures[picture_id].rle_data_len += buf_size;
00202 ctx->pictures[picture_id].rle_remaining_len -= buf_size;
00203
00204 return 0;
00205 }
00206
00207 if (buf_size <= 7)
00208 return -1;
00209 buf_size -= 7;
00210
00211
00212 rle_bitmap_len = bytestream_get_be24(&buf) - 2*2;
00213
00214
00215 width = bytestream_get_be16(&buf);
00216 height = bytestream_get_be16(&buf);
00217
00218
00219 if (avctx->width < width || avctx->height < height) {
00220 av_log(avctx, AV_LOG_ERROR, "Bitmap dimensions larger than video.\n");
00221 return -1;
00222 }
00223
00224 ctx->pictures[picture_id].w = width;
00225 ctx->pictures[picture_id].h = height;
00226
00227 av_fast_malloc(&ctx->pictures[picture_id].rle, &ctx->pictures[picture_id].rle_buffer_size, rle_bitmap_len);
00228
00229 if (!ctx->pictures[picture_id].rle)
00230 return -1;
00231
00232 memcpy(ctx->pictures[picture_id].rle, buf, buf_size);
00233 ctx->pictures[picture_id].rle_data_len = buf_size;
00234 ctx->pictures[picture_id].rle_remaining_len = rle_bitmap_len - buf_size;
00235
00236 return 0;
00237 }
00238
00249 static void parse_palette_segment(AVCodecContext *avctx,
00250 const uint8_t *buf, int buf_size)
00251 {
00252 PGSSubContext *ctx = avctx->priv_data;
00253
00254 const uint8_t *buf_end = buf + buf_size;
00255 const uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;
00256 int color_id;
00257 int y, cb, cr, alpha;
00258 int r, g, b, r_add, g_add, b_add;
00259
00260
00261 buf += 2;
00262
00263 while (buf < buf_end) {
00264 color_id = bytestream_get_byte(&buf);
00265 y = bytestream_get_byte(&buf);
00266 cr = bytestream_get_byte(&buf);
00267 cb = bytestream_get_byte(&buf);
00268 alpha = bytestream_get_byte(&buf);
00269
00270 YUV_TO_RGB1(cb, cr);
00271 YUV_TO_RGB2(r, g, b, y);
00272
00273 av_dlog(avctx, "Color %d := (%d,%d,%d,%d)\n", color_id, r, g, b, alpha);
00274
00275
00276 ctx->clut[color_id] = RGBA(r,g,b,alpha);
00277 }
00278 }
00279
00291 static void parse_presentation_segment(AVCodecContext *avctx,
00292 const uint8_t *buf, int buf_size)
00293 {
00294 PGSSubContext *ctx = avctx->priv_data;
00295
00296 int w = bytestream_get_be16(&buf);
00297 int h = bytestream_get_be16(&buf);
00298
00299 uint16_t object_index;
00300
00301 av_dlog(avctx, "Video Dimensions %dx%d\n",
00302 w, h);
00303 if (av_image_check_size(w, h, 0, avctx) >= 0)
00304 avcodec_set_dimensions(avctx, w, h);
00305
00306
00307 buf++;
00308
00309 ctx->presentation.id_number = bytestream_get_be16(&buf);
00310
00311
00312
00313
00314
00315
00316
00317 buf += 3;
00318
00319 ctx->presentation.object_count = bytestream_get_byte(&buf);
00320 if (!ctx->presentation.object_count)
00321 return;
00322
00323
00324 buf_size -= 11;
00325 if (buf_size < ctx->presentation.object_count * 8) {
00326 ctx->presentation.object_count = 0;
00327 return;
00328 }
00329
00330 av_freep(&ctx->presentation.objects);
00331 ctx->presentation.objects = av_malloc(sizeof(PGSSubPictureReference) * ctx->presentation.object_count);
00332 if (!ctx->presentation.objects) {
00333 ctx->presentation.object_count = 0;
00334 return;
00335 }
00336
00337 for (object_index = 0; object_index < ctx->presentation.object_count; ++object_index) {
00338 PGSSubPictureReference *reference = &ctx->presentation.objects[object_index];
00339 reference->picture_id = bytestream_get_be16(&buf);
00340
00341
00342 buf++;
00343
00344 reference->composition = bytestream_get_byte(&buf);
00345
00346 reference->x = bytestream_get_be16(&buf);
00347 reference->y = bytestream_get_be16(&buf);
00348
00349
00350 av_dlog(avctx, "Subtitle Placement ID=%d, x=%d, y=%d\n", reference->picture_id, reference->x, reference->y);
00351
00352 if (reference->x > avctx->width || reference->y > avctx->height) {
00353 av_log(avctx, AV_LOG_ERROR, "Subtitle out of video bounds. x = %d, y = %d, video width = %d, video height = %d.\n",
00354 reference->x, reference->y, avctx->width, avctx->height);
00355 reference->x = 0;
00356 reference->y = 0;
00357 }
00358 }
00359 }
00360
00376 static int display_end_segment(AVCodecContext *avctx, void *data,
00377 const uint8_t *buf, int buf_size)
00378 {
00379 AVSubtitle *sub = data;
00380 PGSSubContext *ctx = avctx->priv_data;
00381
00382 uint16_t rect;
00383
00384
00385
00386
00387
00388
00389
00390 memset(sub, 0, sizeof(*sub));
00391
00392
00393 if (!ctx->presentation.object_count)
00394 return 1;
00395
00396 sub->start_display_time = 0;
00397 sub->end_display_time = 20000;
00398 sub->format = 0;
00399
00400 sub->num_rects = ctx->presentation.object_count;
00401 sub->rects = av_mallocz(sizeof(*sub->rects) * sub->num_rects);
00402
00403 for (rect = 0; rect < sub->num_rects; ++rect) {
00404 uint16_t picture_id = ctx->presentation.objects[rect].picture_id;
00405 sub->rects[rect] = av_mallocz(sizeof(*sub->rects[rect]));
00406 sub->rects[rect]->x = ctx->presentation.objects[rect].x;
00407 sub->rects[rect]->y = ctx->presentation.objects[rect].y;
00408 sub->rects[rect]->w = ctx->pictures[picture_id].w;
00409 sub->rects[rect]->h = ctx->pictures[picture_id].h;
00410 sub->rects[rect]->type = SUBTITLE_BITMAP;
00411
00412
00413 sub->rects[rect]->pict.linesize[0] = ctx->pictures[picture_id].w;
00414 if (ctx->pictures[picture_id].rle) {
00415 if (ctx->pictures[picture_id].rle_remaining_len)
00416 av_log(avctx, AV_LOG_ERROR, "RLE data length %u is %u bytes shorter than expected\n",
00417 ctx->pictures[picture_id].rle_data_len, ctx->pictures[picture_id].rle_remaining_len);
00418 if (decode_rle(avctx, sub, rect, ctx->pictures[picture_id].rle, ctx->pictures[picture_id].rle_data_len) < 0)
00419 return 0;
00420 }
00421
00422
00423 sub->rects[rect]->nb_colors = 256;
00424 sub->rects[rect]->pict.data[1] = av_mallocz(AVPALETTE_SIZE);
00425
00426
00427 sub->rects[rect]->forced = (ctx->presentation.objects[rect].composition & 0x40) != 0;
00428
00429 if (!ctx->forced_subs_only || ctx->presentation.objects[rect].composition & 0x40)
00430 memcpy(sub->rects[rect]->pict.data[1], ctx->clut, sub->rects[rect]->nb_colors * sizeof(uint32_t));
00431 }
00432
00433 return 1;
00434 }
00435
00436 static int decode(AVCodecContext *avctx, void *data, int *data_size,
00437 AVPacket *avpkt)
00438 {
00439 const uint8_t *buf = avpkt->data;
00440 int buf_size = avpkt->size;
00441
00442 const uint8_t *buf_end;
00443 uint8_t segment_type;
00444 int segment_length;
00445 int i;
00446
00447 av_dlog(avctx, "PGS sub packet:\n");
00448
00449 for (i = 0; i < buf_size; i++) {
00450 av_dlog(avctx, "%02x ", buf[i]);
00451 if (i % 16 == 15)
00452 av_dlog(avctx, "\n");
00453 }
00454
00455 if (i & 15)
00456 av_dlog(avctx, "\n");
00457
00458 *data_size = 0;
00459
00460
00461 if (buf_size < 3)
00462 return -1;
00463
00464 buf_end = buf + buf_size;
00465
00466
00467 while (buf < buf_end) {
00468 segment_type = bytestream_get_byte(&buf);
00469 segment_length = bytestream_get_be16(&buf);
00470
00471 av_dlog(avctx, "Segment Length %d, Segment Type %x\n", segment_length, segment_type);
00472
00473 if (segment_type != DISPLAY_SEGMENT && segment_length > buf_end - buf)
00474 break;
00475
00476 switch (segment_type) {
00477 case PALETTE_SEGMENT:
00478 parse_palette_segment(avctx, buf, segment_length);
00479 break;
00480 case PICTURE_SEGMENT:
00481 parse_picture_segment(avctx, buf, segment_length);
00482 break;
00483 case PRESENTATION_SEGMENT:
00484 parse_presentation_segment(avctx, buf, segment_length);
00485 break;
00486 case WINDOW_SEGMENT:
00487
00488
00489
00490
00491
00492
00493
00494
00495 break;
00496 case DISPLAY_SEGMENT:
00497 *data_size = display_end_segment(avctx, data, buf, segment_length);
00498 break;
00499 default:
00500 av_log(avctx, AV_LOG_ERROR, "Unknown subtitle segment type 0x%x, length %d\n",
00501 segment_type, segment_length);
00502 break;
00503 }
00504
00505 buf += segment_length;
00506 }
00507
00508 return buf_size;
00509 }
00510
00511 #define OFFSET(x) offsetof(PGSSubContext, x)
00512 #define SD AV_OPT_FLAG_SUBTITLE_PARAM | AV_OPT_FLAG_DECODING_PARAM
00513 static const AVOption options[] = {
00514 {"forced_subs_only", "Only show forced subtitles", OFFSET(forced_subs_only), AV_OPT_TYPE_INT, {.dbl = 0}, 0, 1, SD},
00515 { NULL },
00516 };
00517
00518 static const AVClass pgsdec_class = {
00519 .class_name = "PGS subtitle decoder",
00520 .item_name = av_default_item_name,
00521 .option = options,
00522 .version = LIBAVUTIL_VERSION_INT,
00523 };
00524
00525 AVCodec ff_pgssub_decoder = {
00526 .name = "pgssub",
00527 .type = AVMEDIA_TYPE_SUBTITLE,
00528 .id = CODEC_ID_HDMV_PGS_SUBTITLE,
00529 .priv_data_size = sizeof(PGSSubContext),
00530 .init = init_decoder,
00531 .close = close_decoder,
00532 .decode = decode,
00533 .long_name = NULL_IF_CONFIG_SMALL("HDMV Presentation Graphic Stream subtitles"),
00534 .priv_class = &pgsdec_class,
00535 };