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.

479 lines
16KB

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