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.

438 lines
14KB

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