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.

497 lines
16KB

  1. /*
  2. * DVD subtitle encoding
  3. * Copyright (c) 2005 Wolfram Gloger
  4. *
  5. * This file is part of FFmpeg.
  6. *
  7. * FFmpeg is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU Lesser General Public
  9. * License as published by the Free Software Foundation; either
  10. * version 2.1 of the License, or (at your option) any later version.
  11. *
  12. * FFmpeg is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15. * Lesser General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU Lesser General Public
  18. * License along with FFmpeg; if not, write to the Free Software
  19. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  20. */
  21. #include "avcodec.h"
  22. #include "bytestream.h"
  23. #include "internal.h"
  24. #include "libavutil/avassert.h"
  25. #include "libavutil/bprint.h"
  26. #include "libavutil/imgutils.h"
  27. #include "libavutil/opt.h"
  28. typedef struct {
  29. AVClass *class;
  30. uint32_t global_palette[16];
  31. char *palette_str;
  32. int even_rows_fix;
  33. } DVDSubtitleContext;
  34. // ncnt is the nibble counter
  35. #define PUTNIBBLE(val)\
  36. do {\
  37. if (ncnt++ & 1)\
  38. *q++ = bitbuf | ((val) & 0x0f);\
  39. else\
  40. bitbuf = (val) << 4;\
  41. } while(0)
  42. static void dvd_encode_rle(uint8_t **pq,
  43. const uint8_t *bitmap, int linesize,
  44. int w, int h,
  45. const int cmap[256])
  46. {
  47. uint8_t *q;
  48. unsigned int bitbuf = 0;
  49. int ncnt;
  50. int x, y, len, color;
  51. q = *pq;
  52. for (y = 0; y < h; ++y) {
  53. ncnt = 0;
  54. for(x = 0; x < w; x += len) {
  55. color = bitmap[x];
  56. for (len=1; x+len < w; ++len)
  57. if (bitmap[x+len] != color)
  58. break;
  59. color = cmap[color];
  60. av_assert0(color < 4);
  61. if (len < 0x04) {
  62. PUTNIBBLE((len << 2)|color);
  63. } else if (len < 0x10) {
  64. PUTNIBBLE(len >> 2);
  65. PUTNIBBLE((len << 2)|color);
  66. } else if (len < 0x40) {
  67. PUTNIBBLE(0);
  68. PUTNIBBLE(len >> 2);
  69. PUTNIBBLE((len << 2)|color);
  70. } else if (x+len == w) {
  71. PUTNIBBLE(0);
  72. PUTNIBBLE(0);
  73. PUTNIBBLE(0);
  74. PUTNIBBLE(color);
  75. } else {
  76. if (len > 0xff)
  77. len = 0xff;
  78. PUTNIBBLE(0);
  79. PUTNIBBLE(len >> 6);
  80. PUTNIBBLE(len >> 2);
  81. PUTNIBBLE((len << 2)|color);
  82. }
  83. }
  84. /* end of line */
  85. if (ncnt & 1)
  86. PUTNIBBLE(0);
  87. bitmap += linesize;
  88. }
  89. *pq = q;
  90. }
  91. static int color_distance(uint32_t a, uint32_t b)
  92. {
  93. int r = 0, d, i;
  94. int alpha_a = 8, alpha_b = 8;
  95. for (i = 24; i >= 0; i -= 8) {
  96. d = alpha_a * (int)((a >> i) & 0xFF) -
  97. alpha_b * (int)((b >> i) & 0xFF);
  98. r += d * d;
  99. alpha_a = a >> 28;
  100. alpha_b = b >> 28;
  101. }
  102. return r;
  103. }
  104. /**
  105. * Count colors used in a rectangle, quantizing alpha and grouping by
  106. * nearest global palette entry.
  107. */
  108. static void count_colors(AVCodecContext *avctx, unsigned hits[33],
  109. const AVSubtitleRect *r)
  110. {
  111. DVDSubtitleContext *dvdc = avctx->priv_data;
  112. unsigned count[256] = { 0 };
  113. uint32_t *palette = (uint32_t *)r->data[1];
  114. uint32_t color;
  115. int x, y, i, j, match, d, best_d, av_uninit(best_j);
  116. uint8_t *p = r->data[0];
  117. for (y = 0; y < r->h; y++) {
  118. for (x = 0; x < r->w; x++)
  119. count[*(p++)]++;
  120. p += r->linesize[0] - r->w;
  121. }
  122. for (i = 0; i < 256; i++) {
  123. if (!count[i]) /* avoid useless search */
  124. continue;
  125. color = palette[i];
  126. /* 0: transparent, 1-16: semi-transparent, 17-33 opaque */
  127. match = color < 0x33000000 ? 0 : color < 0xCC000000 ? 1 : 17;
  128. if (match) {
  129. best_d = INT_MAX;
  130. for (j = 0; j < 16; j++) {
  131. d = color_distance(0xFF000000 | color,
  132. 0xFF000000 | dvdc->global_palette[j]);
  133. if (d < best_d) {
  134. best_d = d;
  135. best_j = j;
  136. }
  137. }
  138. match += best_j;
  139. }
  140. hits[match] += count[i];
  141. }
  142. }
  143. static void select_palette(AVCodecContext *avctx, int out_palette[4],
  144. int out_alpha[4], unsigned hits[33])
  145. {
  146. DVDSubtitleContext *dvdc = avctx->priv_data;
  147. int i, j, bright, mult;
  148. uint32_t color;
  149. int selected[4] = { 0 };
  150. uint32_t pseudopal[33] = { 0 };
  151. uint32_t refcolor[3] = { 0x00000000, 0xFFFFFFFF, 0xFF000000 };
  152. /* Bonus for transparent: if the rectangle fits tightly the text, the
  153. background color can be quite rare, but it would be ugly without it */
  154. hits[0] *= 16;
  155. /* Bonus for bright colors */
  156. for (i = 0; i < 16; i++) {
  157. if (!(hits[1 + i] + hits[17 + i]))
  158. continue; /* skip unused colors to gain time */
  159. color = dvdc->global_palette[i];
  160. bright = 0;
  161. for (j = 0; j < 3; j++, color >>= 8)
  162. bright += (color & 0xFF) < 0x40 || (color & 0xFF) >= 0xC0;
  163. mult = 2 + FFMIN(bright, 2);
  164. hits[ 1 + i] *= mult;
  165. hits[17 + i] *= mult;
  166. }
  167. /* Select four most frequent colors */
  168. for (i = 0; i < 4; i++) {
  169. for (j = 0; j < 33; j++)
  170. if (hits[j] > hits[selected[i]])
  171. selected[i] = j;
  172. hits[selected[i]] = 0;
  173. }
  174. /* Order the colors like in most DVDs:
  175. 0: background, 1: foreground, 2: outline */
  176. for (i = 0; i < 16; i++) {
  177. pseudopal[ 1 + i] = 0x80000000 | dvdc->global_palette[i];
  178. pseudopal[17 + i] = 0xFF000000 | dvdc->global_palette[i];
  179. }
  180. for (i = 0; i < 3; i++) {
  181. int best_d = color_distance(refcolor[i], pseudopal[selected[i]]);
  182. for (j = i + 1; j < 4; j++) {
  183. int d = color_distance(refcolor[i], pseudopal[selected[j]]);
  184. if (d < best_d) {
  185. FFSWAP(int, selected[i], selected[j]);
  186. best_d = d;
  187. }
  188. }
  189. }
  190. /* Output */
  191. for (i = 0; i < 4; i++) {
  192. out_palette[i] = selected[i] ? (selected[i] - 1) & 0xF : 0;
  193. out_alpha [i] = !selected[i] ? 0 : selected[i] < 17 ? 0x80 : 0xFF;
  194. }
  195. }
  196. static void build_color_map(AVCodecContext *avctx, int cmap[],
  197. const uint32_t palette[],
  198. const int out_palette[], unsigned int const out_alpha[])
  199. {
  200. DVDSubtitleContext *dvdc = avctx->priv_data;
  201. int i, j, d, best_d;
  202. uint32_t pseudopal[4];
  203. for (i = 0; i < 4; i++)
  204. pseudopal[i] = (out_alpha[i] << 24) |
  205. dvdc->global_palette[out_palette[i]];
  206. for (i = 0; i < 256; i++) {
  207. best_d = INT_MAX;
  208. for (j = 0; j < 4; j++) {
  209. d = color_distance(pseudopal[j], palette[i]);
  210. if (d < best_d) {
  211. cmap[i] = j;
  212. best_d = d;
  213. }
  214. }
  215. }
  216. }
  217. static void copy_rectangle(AVSubtitleRect *dst, AVSubtitleRect *src, int cmap[])
  218. {
  219. int x, y;
  220. uint8_t *p, *q;
  221. p = src->data[0];
  222. q = dst->data[0] + (src->x - dst->x) +
  223. (src->y - dst->y) * dst->linesize[0];
  224. for (y = 0; y < src->h; y++) {
  225. for (x = 0; x < src->w; x++)
  226. *(q++) = cmap[*(p++)];
  227. p += src->linesize[0] - src->w;
  228. q += dst->linesize[0] - src->w;
  229. }
  230. }
  231. static int encode_dvd_subtitles(AVCodecContext *avctx,
  232. uint8_t *outbuf, int outbuf_size,
  233. const AVSubtitle *h)
  234. {
  235. DVDSubtitleContext *dvdc = avctx->priv_data;
  236. uint8_t *q, *qq;
  237. int offset1, offset2;
  238. int i, rects = h->num_rects, ret;
  239. unsigned global_palette_hits[33] = { 0 };
  240. int cmap[256];
  241. int out_palette[4];
  242. int out_alpha[4];
  243. AVSubtitleRect vrect;
  244. uint8_t *vrect_data = NULL;
  245. int x2, y2;
  246. int forced = 0;
  247. if (rects == 0 || !h->rects)
  248. return AVERROR(EINVAL);
  249. for (i = 0; i < rects; i++)
  250. if (h->rects[i]->type != SUBTITLE_BITMAP) {
  251. av_log(avctx, AV_LOG_ERROR, "Bitmap subtitle required\n");
  252. return AVERROR(EINVAL);
  253. }
  254. /* Mark this subtitle forced if any of the rectangles is forced. */
  255. for (i = 0; i < rects; i++)
  256. if ((h->rects[i]->flags & AV_SUBTITLE_FLAG_FORCED) != 0) {
  257. forced = 1;
  258. break;
  259. }
  260. #if FF_API_AVPICTURE
  261. FF_DISABLE_DEPRECATION_WARNINGS
  262. for (i = 0; i < rects; i++)
  263. if (!h->rects[i]->data[0]) {
  264. AVSubtitleRect *rect = h->rects[i];
  265. int j;
  266. for (j = 0; j < 4; j++) {
  267. rect->data[j] = rect->pict.data[j];
  268. rect->linesize[j] = rect->pict.linesize[j];
  269. }
  270. }
  271. FF_ENABLE_DEPRECATION_WARNINGS
  272. #endif
  273. vrect = *h->rects[0];
  274. if (rects > 1) {
  275. /* DVD subtitles can have only one rectangle: build a virtual
  276. rectangle containing all actual rectangles.
  277. The data of the rectangles will be copied later, when the palette
  278. is decided, because the rectangles may have different palettes. */
  279. int xmin = h->rects[0]->x, xmax = xmin + h->rects[0]->w;
  280. int ymin = h->rects[0]->y, ymax = ymin + h->rects[0]->h;
  281. for (i = 1; i < rects; i++) {
  282. xmin = FFMIN(xmin, h->rects[i]->x);
  283. ymin = FFMIN(ymin, h->rects[i]->y);
  284. xmax = FFMAX(xmax, h->rects[i]->x + h->rects[i]->w);
  285. ymax = FFMAX(ymax, h->rects[i]->y + h->rects[i]->h);
  286. }
  287. vrect.x = xmin;
  288. vrect.y = ymin;
  289. vrect.w = xmax - xmin;
  290. vrect.h = ymax - ymin;
  291. if ((ret = av_image_check_size(vrect.w, vrect.h, 0, avctx)) < 0)
  292. return ret;
  293. /* Count pixels outside the virtual rectangle as transparent */
  294. global_palette_hits[0] = vrect.w * vrect.h;
  295. for (i = 0; i < rects; i++)
  296. global_palette_hits[0] -= h->rects[i]->w * h->rects[i]->h;
  297. }
  298. for (i = 0; i < rects; i++)
  299. count_colors(avctx, global_palette_hits, h->rects[i]);
  300. select_palette(avctx, out_palette, out_alpha, global_palette_hits);
  301. if (rects > 1) {
  302. if (!(vrect_data = av_calloc(vrect.w, vrect.h)))
  303. return AVERROR(ENOMEM);
  304. vrect.data [0] = vrect_data;
  305. vrect.linesize[0] = vrect.w;
  306. for (i = 0; i < rects; i++) {
  307. build_color_map(avctx, cmap, (uint32_t *)h->rects[i]->data[1],
  308. out_palette, out_alpha);
  309. copy_rectangle(&vrect, h->rects[i], cmap);
  310. }
  311. for (i = 0; i < 4; i++)
  312. cmap[i] = i;
  313. } else {
  314. build_color_map(avctx, cmap, (uint32_t *)h->rects[0]->data[1],
  315. out_palette, out_alpha);
  316. }
  317. av_log(avctx, AV_LOG_DEBUG, "Selected palette:");
  318. for (i = 0; i < 4; i++)
  319. av_log(avctx, AV_LOG_DEBUG, " 0x%06"PRIx32"@@%02x (0x%x,0x%x)",
  320. dvdc->global_palette[out_palette[i]], out_alpha[i],
  321. out_palette[i], out_alpha[i] >> 4);
  322. av_log(avctx, AV_LOG_DEBUG, "\n");
  323. // encode data block
  324. q = outbuf + 4;
  325. offset1 = q - outbuf;
  326. // worst case memory requirement: 1 nibble per pixel..
  327. if ((q - outbuf) + vrect.w * vrect.h / 2 + 17 + 21 > outbuf_size) {
  328. av_log(NULL, AV_LOG_ERROR, "dvd_subtitle too big\n");
  329. ret = AVERROR_BUFFER_TOO_SMALL;
  330. goto fail;
  331. }
  332. dvd_encode_rle(&q, vrect.data[0], vrect.w * 2,
  333. vrect.w, (vrect.h + 1) >> 1, cmap);
  334. offset2 = q - outbuf;
  335. dvd_encode_rle(&q, vrect.data[0] + vrect.w, vrect.w * 2,
  336. vrect.w, vrect.h >> 1, cmap);
  337. if (dvdc->even_rows_fix && (vrect.h & 1)) {
  338. // Work-around for some players that want the height to be even.
  339. vrect.h++;
  340. *q++ = 0x00; // 0x00 0x00 == empty row, i.e. fully transparent
  341. *q++ = 0x00;
  342. }
  343. // set data packet size
  344. qq = outbuf + 2;
  345. bytestream_put_be16(&qq, q - outbuf);
  346. // send start display command
  347. bytestream_put_be16(&q, (h->start_display_time*90) >> 10);
  348. bytestream_put_be16(&q, (q - outbuf) /*- 2 */ + 8 + 12 + 2);
  349. *q++ = 0x03; // palette - 4 nibbles
  350. *q++ = (out_palette[3] << 4) | out_palette[2];
  351. *q++ = (out_palette[1] << 4) | out_palette[0];
  352. *q++ = 0x04; // alpha - 4 nibbles
  353. *q++ = (out_alpha[3] & 0xF0) | (out_alpha[2] >> 4);
  354. *q++ = (out_alpha[1] & 0xF0) | (out_alpha[0] >> 4);
  355. // 12 bytes per rect
  356. x2 = vrect.x + vrect.w - 1;
  357. y2 = vrect.y + vrect.h - 1;
  358. *q++ = 0x05;
  359. // x1 x2 -> 6 nibbles
  360. *q++ = vrect.x >> 4;
  361. *q++ = (vrect.x << 4) | ((x2 >> 8) & 0xf);
  362. *q++ = x2;
  363. // y1 y2 -> 6 nibbles
  364. *q++ = vrect.y >> 4;
  365. *q++ = (vrect.y << 4) | ((y2 >> 8) & 0xf);
  366. *q++ = y2;
  367. *q++ = 0x06;
  368. // offset1, offset2
  369. bytestream_put_be16(&q, offset1);
  370. bytestream_put_be16(&q, offset2);
  371. *q++ = forced ? 0x00 : 0x01; // start command
  372. *q++ = 0xff; // terminating command
  373. // send stop display command last
  374. bytestream_put_be16(&q, (h->end_display_time*90) >> 10);
  375. bytestream_put_be16(&q, (q - outbuf) - 2 /*+ 4*/);
  376. *q++ = 0x02; // set end
  377. *q++ = 0xff; // terminating command
  378. qq = outbuf;
  379. bytestream_put_be16(&qq, q - outbuf);
  380. av_log(NULL, AV_LOG_DEBUG, "subtitle_packet size=%"PTRDIFF_SPECIFIER"\n", q - outbuf);
  381. ret = q - outbuf;
  382. fail:
  383. av_free(vrect_data);
  384. return ret;
  385. }
  386. static int dvdsub_init(AVCodecContext *avctx)
  387. {
  388. DVDSubtitleContext *dvdc = avctx->priv_data;
  389. static const uint32_t default_palette[16] = {
  390. 0x000000, 0x0000FF, 0x00FF00, 0xFF0000,
  391. 0xFFFF00, 0xFF00FF, 0x00FFFF, 0xFFFFFF,
  392. 0x808000, 0x8080FF, 0x800080, 0x80FF80,
  393. 0x008080, 0xFF8080, 0x555555, 0xAAAAAA,
  394. };
  395. AVBPrint extradata;
  396. int i, ret;
  397. av_assert0(sizeof(dvdc->global_palette) == sizeof(default_palette));
  398. if (dvdc->palette_str) {
  399. ff_dvdsub_parse_palette(dvdc->global_palette, dvdc->palette_str);
  400. } else {
  401. memcpy(dvdc->global_palette, default_palette, sizeof(dvdc->global_palette));
  402. }
  403. av_bprint_init(&extradata, 0, AV_BPRINT_SIZE_AUTOMATIC);
  404. if (avctx->width && avctx->height)
  405. av_bprintf(&extradata, "size: %dx%d\n", avctx->width, avctx->height);
  406. av_bprintf(&extradata, "palette:");
  407. for (i = 0; i < 16; i++)
  408. av_bprintf(&extradata, " %06"PRIx32"%c",
  409. dvdc->global_palette[i] & 0xFFFFFF, i < 15 ? ',' : '\n');
  410. ret = avpriv_bprint_to_extradata(avctx, &extradata);
  411. if (ret < 0)
  412. return ret;
  413. return 0;
  414. }
  415. static int dvdsub_encode(AVCodecContext *avctx,
  416. unsigned char *buf, int buf_size,
  417. const AVSubtitle *sub)
  418. {
  419. //DVDSubtitleContext *s = avctx->priv_data;
  420. int ret;
  421. ret = encode_dvd_subtitles(avctx, buf, buf_size, sub);
  422. return ret;
  423. }
  424. #define OFFSET(x) offsetof(DVDSubtitleContext, x)
  425. #define SE AV_OPT_FLAG_SUBTITLE_PARAM | AV_OPT_FLAG_ENCODING_PARAM
  426. static const AVOption options[] = {
  427. {"palette", "set the global palette", OFFSET(palette_str), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, SE },
  428. {"even_rows_fix", "Make number of rows even (workaround for some players)", OFFSET(even_rows_fix), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, SE},
  429. { NULL },
  430. };
  431. static const AVClass dvdsubenc_class = {
  432. .class_name = "VOBSUB subtitle encoder",
  433. .item_name = av_default_item_name,
  434. .option = options,
  435. .version = LIBAVUTIL_VERSION_INT,
  436. };
  437. AVCodec ff_dvdsub_encoder = {
  438. .name = "dvdsub",
  439. .long_name = NULL_IF_CONFIG_SMALL("DVD subtitles"),
  440. .type = AVMEDIA_TYPE_SUBTITLE,
  441. .id = AV_CODEC_ID_DVD_SUBTITLE,
  442. .init = dvdsub_init,
  443. .encode_sub = dvdsub_encode,
  444. .priv_class = &dvdsubenc_class,
  445. .priv_data_size = sizeof(DVDSubtitleContext),
  446. };