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.

476 lines
15KB

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