smc.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489
  1. /*
  2. * Quicktime Graphics (SMC) Video Decoder
  3. * Copyright (C) 2003 the ffmpeg project
  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. /**
  22. * @file libavcodec/smc.c
  23. * QT SMC Video Decoder by Mike Melanson (melanson@pcisys.net)
  24. * For more information about the SMC format, visit:
  25. * http://www.pcisys.net/~melanson/codecs/
  26. *
  27. * The SMC decoder outputs PAL8 colorspace data.
  28. */
  29. #include <stdio.h>
  30. #include <stdlib.h>
  31. #include <string.h>
  32. #include <unistd.h>
  33. #include "libavutil/intreadwrite.h"
  34. #include "avcodec.h"
  35. #define CPAIR 2
  36. #define CQUAD 4
  37. #define COCTET 8
  38. #define COLORS_PER_TABLE 256
  39. typedef struct SmcContext {
  40. AVCodecContext *avctx;
  41. AVFrame frame;
  42. const unsigned char *buf;
  43. int size;
  44. /* SMC color tables */
  45. unsigned char color_pairs[COLORS_PER_TABLE * CPAIR];
  46. unsigned char color_quads[COLORS_PER_TABLE * CQUAD];
  47. unsigned char color_octets[COLORS_PER_TABLE * COCTET];
  48. } SmcContext;
  49. #define GET_BLOCK_COUNT() \
  50. (opcode & 0x10) ? (1 + s->buf[stream_ptr++]) : 1 + (opcode & 0x0F);
  51. #define ADVANCE_BLOCK() \
  52. { \
  53. pixel_ptr += 4; \
  54. if (pixel_ptr >= width) \
  55. { \
  56. pixel_ptr = 0; \
  57. row_ptr += stride * 4; \
  58. } \
  59. total_blocks--; \
  60. if (total_blocks < 0 + !!n_blocks) \
  61. { \
  62. av_log(s->avctx, AV_LOG_INFO, "warning: block counter just went negative (this should not happen)\n"); \
  63. return; \
  64. } \
  65. }
  66. static void smc_decode_stream(SmcContext *s)
  67. {
  68. int width = s->avctx->width;
  69. int height = s->avctx->height;
  70. int stride = s->frame.linesize[0];
  71. int i;
  72. int stream_ptr = 0;
  73. int chunk_size;
  74. unsigned char opcode;
  75. int n_blocks;
  76. unsigned int color_flags;
  77. unsigned int color_flags_a;
  78. unsigned int color_flags_b;
  79. unsigned int flag_mask;
  80. unsigned char *pixels = s->frame.data[0];
  81. int image_size = height * s->frame.linesize[0];
  82. int row_ptr = 0;
  83. int pixel_ptr = 0;
  84. int pixel_x, pixel_y;
  85. int row_inc = stride - 4;
  86. int block_ptr;
  87. int prev_block_ptr;
  88. int prev_block_ptr1, prev_block_ptr2;
  89. int prev_block_flag;
  90. int total_blocks;
  91. int color_table_index; /* indexes to color pair, quad, or octet tables */
  92. int pixel;
  93. int color_pair_index = 0;
  94. int color_quad_index = 0;
  95. int color_octet_index = 0;
  96. /* make the palette available */
  97. memcpy(s->frame.data[1], s->avctx->palctrl->palette, AVPALETTE_SIZE);
  98. if (s->avctx->palctrl->palette_changed) {
  99. s->frame.palette_has_changed = 1;
  100. s->avctx->palctrl->palette_changed = 0;
  101. }
  102. chunk_size = AV_RB32(&s->buf[stream_ptr]) & 0x00FFFFFF;
  103. stream_ptr += 4;
  104. if (chunk_size != s->size)
  105. av_log(s->avctx, AV_LOG_INFO, "warning: MOV chunk size != encoded chunk size (%d != %d); using MOV chunk size\n",
  106. chunk_size, s->size);
  107. chunk_size = s->size;
  108. total_blocks = ((s->avctx->width + 3) / 4) * ((s->avctx->height + 3) / 4);
  109. /* traverse through the blocks */
  110. while (total_blocks) {
  111. /* sanity checks */
  112. /* make sure stream ptr hasn't gone out of bounds */
  113. if (stream_ptr > chunk_size) {
  114. av_log(s->avctx, AV_LOG_INFO, "SMC decoder just went out of bounds (stream ptr = %d, chunk size = %d)\n",
  115. stream_ptr, chunk_size);
  116. return;
  117. }
  118. /* make sure the row pointer hasn't gone wild */
  119. if (row_ptr >= image_size) {
  120. av_log(s->avctx, AV_LOG_INFO, "SMC decoder just went out of bounds (row ptr = %d, height = %d)\n",
  121. row_ptr, image_size);
  122. return;
  123. }
  124. opcode = s->buf[stream_ptr++];
  125. switch (opcode & 0xF0) {
  126. /* skip n blocks */
  127. case 0x00:
  128. case 0x10:
  129. n_blocks = GET_BLOCK_COUNT();
  130. while (n_blocks--) {
  131. ADVANCE_BLOCK();
  132. }
  133. break;
  134. /* repeat last block n times */
  135. case 0x20:
  136. case 0x30:
  137. n_blocks = GET_BLOCK_COUNT();
  138. /* sanity check */
  139. if ((row_ptr == 0) && (pixel_ptr == 0)) {
  140. av_log(s->avctx, AV_LOG_INFO, "encountered repeat block opcode (%02X) but no blocks rendered yet\n",
  141. opcode & 0xF0);
  142. break;
  143. }
  144. /* figure out where the previous block started */
  145. if (pixel_ptr == 0)
  146. prev_block_ptr1 =
  147. (row_ptr - s->avctx->width * 4) + s->avctx->width - 4;
  148. else
  149. prev_block_ptr1 = row_ptr + pixel_ptr - 4;
  150. while (n_blocks--) {
  151. block_ptr = row_ptr + pixel_ptr;
  152. prev_block_ptr = prev_block_ptr1;
  153. for (pixel_y = 0; pixel_y < 4; pixel_y++) {
  154. for (pixel_x = 0; pixel_x < 4; pixel_x++) {
  155. pixels[block_ptr++] = pixels[prev_block_ptr++];
  156. }
  157. block_ptr += row_inc;
  158. prev_block_ptr += row_inc;
  159. }
  160. ADVANCE_BLOCK();
  161. }
  162. break;
  163. /* repeat previous pair of blocks n times */
  164. case 0x40:
  165. case 0x50:
  166. n_blocks = GET_BLOCK_COUNT();
  167. n_blocks *= 2;
  168. /* sanity check */
  169. if ((row_ptr == 0) && (pixel_ptr < 2 * 4)) {
  170. av_log(s->avctx, AV_LOG_INFO, "encountered repeat block opcode (%02X) but not enough blocks rendered yet\n",
  171. opcode & 0xF0);
  172. break;
  173. }
  174. /* figure out where the previous 2 blocks started */
  175. if (pixel_ptr == 0)
  176. prev_block_ptr1 = (row_ptr - s->avctx->width * 4) +
  177. s->avctx->width - 4 * 2;
  178. else if (pixel_ptr == 4)
  179. prev_block_ptr1 = (row_ptr - s->avctx->width * 4) + row_inc;
  180. else
  181. prev_block_ptr1 = row_ptr + pixel_ptr - 4 * 2;
  182. if (pixel_ptr == 0)
  183. prev_block_ptr2 = (row_ptr - s->avctx->width * 4) + row_inc;
  184. else
  185. prev_block_ptr2 = row_ptr + pixel_ptr - 4;
  186. prev_block_flag = 0;
  187. while (n_blocks--) {
  188. block_ptr = row_ptr + pixel_ptr;
  189. if (prev_block_flag)
  190. prev_block_ptr = prev_block_ptr2;
  191. else
  192. prev_block_ptr = prev_block_ptr1;
  193. prev_block_flag = !prev_block_flag;
  194. for (pixel_y = 0; pixel_y < 4; pixel_y++) {
  195. for (pixel_x = 0; pixel_x < 4; pixel_x++) {
  196. pixels[block_ptr++] = pixels[prev_block_ptr++];
  197. }
  198. block_ptr += row_inc;
  199. prev_block_ptr += row_inc;
  200. }
  201. ADVANCE_BLOCK();
  202. }
  203. break;
  204. /* 1-color block encoding */
  205. case 0x60:
  206. case 0x70:
  207. n_blocks = GET_BLOCK_COUNT();
  208. pixel = s->buf[stream_ptr++];
  209. while (n_blocks--) {
  210. block_ptr = row_ptr + pixel_ptr;
  211. for (pixel_y = 0; pixel_y < 4; pixel_y++) {
  212. for (pixel_x = 0; pixel_x < 4; pixel_x++) {
  213. pixels[block_ptr++] = pixel;
  214. }
  215. block_ptr += row_inc;
  216. }
  217. ADVANCE_BLOCK();
  218. }
  219. break;
  220. /* 2-color block encoding */
  221. case 0x80:
  222. case 0x90:
  223. n_blocks = (opcode & 0x0F) + 1;
  224. /* figure out which color pair to use to paint the 2-color block */
  225. if ((opcode & 0xF0) == 0x80) {
  226. /* fetch the next 2 colors from bytestream and store in next
  227. * available entry in the color pair table */
  228. for (i = 0; i < CPAIR; i++) {
  229. pixel = s->buf[stream_ptr++];
  230. color_table_index = CPAIR * color_pair_index + i;
  231. s->color_pairs[color_table_index] = pixel;
  232. }
  233. /* this is the base index to use for this block */
  234. color_table_index = CPAIR * color_pair_index;
  235. color_pair_index++;
  236. /* wraparound */
  237. if (color_pair_index == COLORS_PER_TABLE)
  238. color_pair_index = 0;
  239. } else
  240. color_table_index = CPAIR * s->buf[stream_ptr++];
  241. while (n_blocks--) {
  242. color_flags = AV_RB16(&s->buf[stream_ptr]);
  243. stream_ptr += 2;
  244. flag_mask = 0x8000;
  245. block_ptr = row_ptr + pixel_ptr;
  246. for (pixel_y = 0; pixel_y < 4; pixel_y++) {
  247. for (pixel_x = 0; pixel_x < 4; pixel_x++) {
  248. if (color_flags & flag_mask)
  249. pixel = color_table_index + 1;
  250. else
  251. pixel = color_table_index;
  252. flag_mask >>= 1;
  253. pixels[block_ptr++] = s->color_pairs[pixel];
  254. }
  255. block_ptr += row_inc;
  256. }
  257. ADVANCE_BLOCK();
  258. }
  259. break;
  260. /* 4-color block encoding */
  261. case 0xA0:
  262. case 0xB0:
  263. n_blocks = (opcode & 0x0F) + 1;
  264. /* figure out which color quad to use to paint the 4-color block */
  265. if ((opcode & 0xF0) == 0xA0) {
  266. /* fetch the next 4 colors from bytestream and store in next
  267. * available entry in the color quad table */
  268. for (i = 0; i < CQUAD; i++) {
  269. pixel = s->buf[stream_ptr++];
  270. color_table_index = CQUAD * color_quad_index + i;
  271. s->color_quads[color_table_index] = pixel;
  272. }
  273. /* this is the base index to use for this block */
  274. color_table_index = CQUAD * color_quad_index;
  275. color_quad_index++;
  276. /* wraparound */
  277. if (color_quad_index == COLORS_PER_TABLE)
  278. color_quad_index = 0;
  279. } else
  280. color_table_index = CQUAD * s->buf[stream_ptr++];
  281. while (n_blocks--) {
  282. color_flags = AV_RB32(&s->buf[stream_ptr]);
  283. stream_ptr += 4;
  284. /* flag mask actually acts as a bit shift count here */
  285. flag_mask = 30;
  286. block_ptr = row_ptr + pixel_ptr;
  287. for (pixel_y = 0; pixel_y < 4; pixel_y++) {
  288. for (pixel_x = 0; pixel_x < 4; pixel_x++) {
  289. pixel = color_table_index +
  290. ((color_flags >> flag_mask) & 0x03);
  291. flag_mask -= 2;
  292. pixels[block_ptr++] = s->color_quads[pixel];
  293. }
  294. block_ptr += row_inc;
  295. }
  296. ADVANCE_BLOCK();
  297. }
  298. break;
  299. /* 8-color block encoding */
  300. case 0xC0:
  301. case 0xD0:
  302. n_blocks = (opcode & 0x0F) + 1;
  303. /* figure out which color octet to use to paint the 8-color block */
  304. if ((opcode & 0xF0) == 0xC0) {
  305. /* fetch the next 8 colors from bytestream and store in next
  306. * available entry in the color octet table */
  307. for (i = 0; i < COCTET; i++) {
  308. pixel = s->buf[stream_ptr++];
  309. color_table_index = COCTET * color_octet_index + i;
  310. s->color_octets[color_table_index] = pixel;
  311. }
  312. /* this is the base index to use for this block */
  313. color_table_index = COCTET * color_octet_index;
  314. color_octet_index++;
  315. /* wraparound */
  316. if (color_octet_index == COLORS_PER_TABLE)
  317. color_octet_index = 0;
  318. } else
  319. color_table_index = COCTET * s->buf[stream_ptr++];
  320. while (n_blocks--) {
  321. /*
  322. For this input of 6 hex bytes:
  323. 01 23 45 67 89 AB
  324. Mangle it to this output:
  325. flags_a = xx012456, flags_b = xx89A37B
  326. */
  327. /* build the color flags */
  328. color_flags_a = color_flags_b = 0;
  329. color_flags_a =
  330. (s->buf[stream_ptr + 0] << 16) |
  331. ((s->buf[stream_ptr + 1] & 0xF0) << 8) |
  332. ((s->buf[stream_ptr + 2] & 0xF0) << 4) |
  333. ((s->buf[stream_ptr + 2] & 0x0F) << 4) |
  334. ((s->buf[stream_ptr + 3] & 0xF0) >> 4);
  335. color_flags_b =
  336. (s->buf[stream_ptr + 4] << 16) |
  337. ((s->buf[stream_ptr + 5] & 0xF0) << 8) |
  338. ((s->buf[stream_ptr + 1] & 0x0F) << 8) |
  339. ((s->buf[stream_ptr + 3] & 0x0F) << 4) |
  340. (s->buf[stream_ptr + 5] & 0x0F);
  341. stream_ptr += 6;
  342. color_flags = color_flags_a;
  343. /* flag mask actually acts as a bit shift count here */
  344. flag_mask = 21;
  345. block_ptr = row_ptr + pixel_ptr;
  346. for (pixel_y = 0; pixel_y < 4; pixel_y++) {
  347. /* reload flags at third row (iteration pixel_y == 2) */
  348. if (pixel_y == 2) {
  349. color_flags = color_flags_b;
  350. flag_mask = 21;
  351. }
  352. for (pixel_x = 0; pixel_x < 4; pixel_x++) {
  353. pixel = color_table_index +
  354. ((color_flags >> flag_mask) & 0x07);
  355. flag_mask -= 3;
  356. pixels[block_ptr++] = s->color_octets[pixel];
  357. }
  358. block_ptr += row_inc;
  359. }
  360. ADVANCE_BLOCK();
  361. }
  362. break;
  363. /* 16-color block encoding (every pixel is a different color) */
  364. case 0xE0:
  365. n_blocks = (opcode & 0x0F) + 1;
  366. while (n_blocks--) {
  367. block_ptr = row_ptr + pixel_ptr;
  368. for (pixel_y = 0; pixel_y < 4; pixel_y++) {
  369. for (pixel_x = 0; pixel_x < 4; pixel_x++) {
  370. pixels[block_ptr++] = s->buf[stream_ptr++];
  371. }
  372. block_ptr += row_inc;
  373. }
  374. ADVANCE_BLOCK();
  375. }
  376. break;
  377. case 0xF0:
  378. av_log(s->avctx, AV_LOG_INFO, "0xF0 opcode seen in SMC chunk (contact the developers)\n");
  379. break;
  380. }
  381. }
  382. }
  383. static av_cold int smc_decode_init(AVCodecContext *avctx)
  384. {
  385. SmcContext *s = avctx->priv_data;
  386. s->avctx = avctx;
  387. avctx->pix_fmt = PIX_FMT_PAL8;
  388. s->frame.data[0] = NULL;
  389. return 0;
  390. }
  391. static int smc_decode_frame(AVCodecContext *avctx,
  392. void *data, int *data_size,
  393. const uint8_t *buf, int buf_size)
  394. {
  395. SmcContext *s = avctx->priv_data;
  396. s->buf = buf;
  397. s->size = buf_size;
  398. s->frame.reference = 1;
  399. s->frame.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE |
  400. FF_BUFFER_HINTS_REUSABLE | FF_BUFFER_HINTS_READABLE;
  401. if (avctx->reget_buffer(avctx, &s->frame)) {
  402. av_log(s->avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
  403. return -1;
  404. }
  405. smc_decode_stream(s);
  406. *data_size = sizeof(AVFrame);
  407. *(AVFrame*)data = s->frame;
  408. /* always report that the buffer was completely consumed */
  409. return buf_size;
  410. }
  411. static av_cold int smc_decode_end(AVCodecContext *avctx)
  412. {
  413. SmcContext *s = avctx->priv_data;
  414. if (s->frame.data[0])
  415. avctx->release_buffer(avctx, &s->frame);
  416. return 0;
  417. }
  418. AVCodec smc_decoder = {
  419. "smc",
  420. CODEC_TYPE_VIDEO,
  421. CODEC_ID_SMC,
  422. sizeof(SmcContext),
  423. smc_decode_init,
  424. NULL,
  425. smc_decode_end,
  426. smc_decode_frame,
  427. CODEC_CAP_DR1,
  428. .long_name = NULL_IF_CONFIG_SMALL("QuickTime Graphics (SMC)"),
  429. };