You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

117 lines
3.5KB

  1. #include "avcodec.h"
  2. #include "bitstream.h"
  3. #include "bytestream.h"
  4. static int decode_init(AVCodecContext *avctx) {
  5. avctx->pix_fmt = PIX_FMT_PAL8;
  6. return 0;
  7. }
  8. static const uint8_t tc_offsets[9] = { 0, 1, 3, 4, 6, 7, 9, 10, 11 };
  9. static const uint8_t tc_muls[9] = { 10, 6, 10, 6, 10, 6, 10, 10, 1 };
  10. static uint64_t parse_timecode(uint8_t *buf) {
  11. int i;
  12. int64_t ms = 0;
  13. if (buf[2] != ':' || buf[5] != ':' || buf[8] != '.')
  14. return AV_NOPTS_VALUE;
  15. for (i = 0; i < sizeof(tc_offsets); i++) {
  16. uint8_t c = buf[tc_offsets[i]] - '0';
  17. if (c > 9) return AV_NOPTS_VALUE;
  18. ms = (ms + c) * tc_muls[i];
  19. }
  20. return ms;
  21. }
  22. static int decode_frame(AVCodecContext *avctx, void *data, int *data_size,
  23. uint8_t *buf, int buf_size) {
  24. AVSubtitle *sub = data;
  25. uint8_t *buf_end = buf + buf_size;
  26. uint8_t *bitmap;
  27. int w, h, x, y, rlelen, i;
  28. GetBitContext gb;
  29. // check that at least header fits
  30. if (buf_size < 27 + 7 * 2 + 4 * 3) {
  31. av_log(avctx, AV_LOG_ERROR, "coded frame too small\n");
  32. return -1;
  33. }
  34. // read start and end time
  35. if (buf[0] != '[' || buf[13] != '-' || buf[26] != ']') {
  36. av_log(avctx, AV_LOG_ERROR, "invalid time code\n");
  37. return -1;
  38. }
  39. sub->start_display_time = parse_timecode(buf + 1);
  40. sub->end_display_time = parse_timecode(buf + 14);
  41. buf += 27;
  42. // read header
  43. w = bytestream_get_le16(&buf);
  44. h = bytestream_get_le16(&buf);
  45. if (avcodec_check_dimensions(avctx, w, h) < 0)
  46. return -1;
  47. x = bytestream_get_le16(&buf);
  48. y = bytestream_get_le16(&buf);
  49. // skip bottom right position, it gives no new information
  50. bytestream_get_le16(&buf);
  51. bytestream_get_le16(&buf);
  52. rlelen = bytestream_get_le16(&buf);
  53. // allocate sub and set values
  54. if (!sub->rects) {
  55. sub->rects = av_mallocz(sizeof(AVSubtitleRect));
  56. sub->num_rects = 1;
  57. }
  58. av_freep(&sub->rects[0].bitmap);
  59. sub->rects[0].x = x; sub->rects[0].y = y;
  60. sub->rects[0].w = w; sub->rects[0].h = h;
  61. sub->rects[0].linesize = w;
  62. sub->rects[0].bitmap = av_malloc(w * h);
  63. sub->rects[0].nb_colors = 4;
  64. sub->rects[0].rgba_palette = av_malloc(sub->rects[0].nb_colors * 4);
  65. // read palette
  66. for (i = 0; i < sub->rects[0].nb_colors; i++)
  67. sub->rects[0].rgba_palette[i] = bytestream_get_be24(&buf);
  68. // make all except background (first entry) non-transparent
  69. for (i = 1; i < sub->rects[0].nb_colors; i++)
  70. sub->rects[0].rgba_palette[i] |= 0xff000000;
  71. // process RLE-compressed data
  72. rlelen = FFMIN(rlelen, buf_end - buf);
  73. init_get_bits(&gb, buf, rlelen * 8);
  74. bitmap = sub->rects[0].bitmap;
  75. for (y = 0; y < h; y++) {
  76. // interlaced: do odd lines
  77. if (y == (h + 1) / 2) bitmap = sub->rects[0].bitmap + w;
  78. for (x = 0; x < w; ) {
  79. int log2 = ff_log2_tab[show_bits(&gb, 8)];
  80. int run = get_bits(&gb, 14 - 4 * (log2 >> 1));
  81. int colour = get_bits(&gb, 2);
  82. run = FFMIN(run, w - x);
  83. // run length 0 means till end of row
  84. if (!run) run = w - x;
  85. memset(bitmap, colour, run);
  86. bitmap += run;
  87. x += run;
  88. }
  89. // interlaced, skip every second line
  90. bitmap += w;
  91. align_get_bits(&gb);
  92. }
  93. *data_size = 1;
  94. return buf_size;
  95. }
  96. AVCodec xsub_decoder = {
  97. "xsub",
  98. CODEC_TYPE_SUBTITLE,
  99. CODEC_ID_XSUB,
  100. 0,
  101. decode_init,
  102. NULL,
  103. NULL,
  104. decode_frame,
  105. };