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.

461 lines
14KB

  1. /*
  2. * Cinepak Video Decoder
  3. * Copyright (C) 2003 the ffmpeg project
  4. *
  5. * This library is free software; you can redistribute it and/or
  6. * modify it under the terms of the GNU Lesser General Public
  7. * License as published by the Free Software Foundation; either
  8. * version 2 of the License, or (at your option) any later version.
  9. *
  10. * This library is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  13. * Lesser General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU Lesser General Public
  16. * License along with this library; if not, write to the Free Software
  17. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  18. *
  19. */
  20. /**
  21. * @file cinepak.c
  22. * Cinepak video decoder
  23. * by Ewald Snel <ewald@rambo.its.tudelft.nl>
  24. * For more information on the Cinepak algorithm, visit:
  25. * http://www.csse.monash.edu.au/~timf/
  26. */
  27. #include <stdio.h>
  28. #include <stdlib.h>
  29. #include <string.h>
  30. #include <unistd.h>
  31. #include "common.h"
  32. #include "avcodec.h"
  33. #include "dsputil.h"
  34. #define PALETTE_COUNT 256
  35. #define BE_16(x) ((((uint8_t*)(x))[0] << 8) | ((uint8_t*)(x))[1])
  36. #define BE_32(x) ((((uint8_t*)(x))[0] << 24) | \
  37. (((uint8_t*)(x))[1] << 16) | \
  38. (((uint8_t*)(x))[2] << 8) | \
  39. ((uint8_t*)(x))[3])
  40. typedef struct {
  41. uint8_t y0, y1, y2, y3;
  42. uint8_t u, v;
  43. } cvid_codebook_t;
  44. #define MAX_STRIPS 32
  45. typedef struct {
  46. uint16_t id;
  47. uint16_t x1, y1;
  48. uint16_t x2, y2;
  49. cvid_codebook_t v4_codebook[256];
  50. cvid_codebook_t v1_codebook[256];
  51. } cvid_strip_t;
  52. typedef struct CinepakContext {
  53. AVCodecContext *avctx;
  54. DSPContext dsp;
  55. AVFrame frame;
  56. AVFrame prev_frame;
  57. unsigned char *data;
  58. int size;
  59. int width, height;
  60. unsigned char palette[PALETTE_COUNT * 4];
  61. int palette_video;
  62. cvid_strip_t strips[MAX_STRIPS];
  63. } CinepakContext;
  64. static void cinepak_decode_codebook (cvid_codebook_t *codebook,
  65. int chunk_id, int size, uint8_t *data)
  66. {
  67. uint8_t *eod = (data + size);
  68. uint32_t flag, mask;
  69. int i, n;
  70. /* check if this chunk contains 4- or 6-element vectors */
  71. n = (chunk_id & 0x0400) ? 4 : 6;
  72. flag = 0;
  73. mask = 0;
  74. for (i=0; i < 256; i++) {
  75. if ((chunk_id & 0x0100) && !(mask >>= 1)) {
  76. if ((data + 4) > eod)
  77. break;
  78. flag = BE_32 (data);
  79. data += 4;
  80. mask = 0x80000000;
  81. }
  82. if (!(chunk_id & 0x0100) || (flag & mask)) {
  83. if ((data + n) > eod)
  84. break;
  85. if (n == 6) {
  86. codebook[i].y0 = *data++;
  87. codebook[i].y1 = *data++;
  88. codebook[i].y2 = *data++;
  89. codebook[i].y3 = *data++;
  90. codebook[i].u = 128 + *data++;
  91. codebook[i].v = 128 + *data++;
  92. } else {
  93. /* this codebook type indicates either greyscale or
  94. * palettized video; if palettized, U & V components will
  95. * not be used so it is safe to set them to 128 for the
  96. * benefit of greyscale rendering in YUV420P */
  97. codebook[i].y0 = *data++;
  98. codebook[i].y1 = *data++;
  99. codebook[i].y2 = *data++;
  100. codebook[i].y3 = *data++;
  101. codebook[i].u = 128;
  102. codebook[i].v = 128;
  103. }
  104. }
  105. }
  106. }
  107. static int cinepak_decode_vectors (CinepakContext *s, cvid_strip_t *strip,
  108. int chunk_id, int size, uint8_t *data)
  109. {
  110. uint8_t *eod = (data + size);
  111. uint32_t flag, mask;
  112. cvid_codebook_t *codebook;
  113. unsigned int i, j, x, y;
  114. uint32_t iy[4];
  115. uint32_t iu[2];
  116. uint32_t iv[2];
  117. flag = 0;
  118. mask = 0;
  119. for (y=strip->y1; y < strip->y2; y+=4) {
  120. iy[0] = strip->x1 + (y * s->frame.linesize[0]);
  121. iy[1] = iy[0] + s->frame.linesize[0];
  122. iy[2] = iy[1] + s->frame.linesize[0];
  123. iy[3] = iy[2] + s->frame.linesize[0];
  124. iu[0] = (strip->x1/2) + ((y/2) * s->frame.linesize[1]);
  125. iu[1] = iu[0] + s->frame.linesize[1];
  126. iv[0] = (strip->x1/2) + ((y/2) * s->frame.linesize[2]);
  127. iv[1] = iv[0] + s->frame.linesize[2];
  128. for (x=strip->x1; x < strip->x2; x+=4) {
  129. if ((chunk_id & 0x0100) && !(mask >>= 1)) {
  130. if ((data + 4) > eod)
  131. return -1;
  132. flag = BE_32 (data);
  133. data += 4;
  134. mask = 0x80000000;
  135. }
  136. if (!(chunk_id & 0x0100) || (flag & mask)) {
  137. if (!(chunk_id & 0x0200) && !(mask >>= 1)) {
  138. if ((data + 4) > eod)
  139. return -1;
  140. flag = BE_32 (data);
  141. data += 4;
  142. mask = 0x80000000;
  143. }
  144. if ((chunk_id & 0x0200) || (~flag & mask)) {
  145. if (data >= eod)
  146. return -1;
  147. codebook = &strip->v1_codebook[*data++];
  148. s->frame.data[0][iy[0] + 0] = codebook->y0;
  149. s->frame.data[0][iy[0] + 1] = codebook->y0;
  150. s->frame.data[0][iy[1] + 0] = codebook->y0;
  151. s->frame.data[0][iy[1] + 1] = codebook->y0;
  152. if (!s->palette_video) {
  153. s->frame.data[1][iu[0]] = codebook->u;
  154. s->frame.data[2][iv[0]] = codebook->v;
  155. }
  156. s->frame.data[0][iy[0] + 2] = codebook->y0;
  157. s->frame.data[0][iy[0] + 3] = codebook->y0;
  158. s->frame.data[0][iy[1] + 2] = codebook->y0;
  159. s->frame.data[0][iy[1] + 3] = codebook->y0;
  160. if (!s->palette_video) {
  161. s->frame.data[1][iu[0] + 1] = codebook->u;
  162. s->frame.data[2][iv[0] + 1] = codebook->v;
  163. }
  164. s->frame.data[0][iy[2] + 0] = codebook->y0;
  165. s->frame.data[0][iy[2] + 1] = codebook->y0;
  166. s->frame.data[0][iy[3] + 0] = codebook->y0;
  167. s->frame.data[0][iy[3] + 1] = codebook->y0;
  168. if (!s->palette_video) {
  169. s->frame.data[1][iu[1]] = codebook->u;
  170. s->frame.data[2][iv[1]] = codebook->v;
  171. }
  172. s->frame.data[0][iy[2] + 2] = codebook->y0;
  173. s->frame.data[0][iy[2] + 3] = codebook->y0;
  174. s->frame.data[0][iy[3] + 2] = codebook->y0;
  175. s->frame.data[0][iy[3] + 3] = codebook->y0;
  176. if (!s->palette_video) {
  177. s->frame.data[1][iu[1] + 1] = codebook->u;
  178. s->frame.data[2][iv[1] + 1] = codebook->v;
  179. }
  180. } else if (flag & mask) {
  181. if ((data + 4) > eod)
  182. return -1;
  183. codebook = &strip->v4_codebook[*data++];
  184. s->frame.data[0][iy[0] + 0] = codebook->y0;
  185. s->frame.data[0][iy[0] + 1] = codebook->y1;
  186. s->frame.data[0][iy[1] + 0] = codebook->y2;
  187. s->frame.data[0][iy[1] + 1] = codebook->y3;
  188. if (!s->palette_video) {
  189. s->frame.data[1][iu[0]] = codebook->u;
  190. s->frame.data[2][iv[0]] = codebook->v;
  191. }
  192. codebook = &strip->v4_codebook[*data++];
  193. s->frame.data[0][iy[0] + 2] = codebook->y0;
  194. s->frame.data[0][iy[0] + 3] = codebook->y1;
  195. s->frame.data[0][iy[1] + 2] = codebook->y2;
  196. s->frame.data[0][iy[1] + 3] = codebook->y3;
  197. if (!s->palette_video) {
  198. s->frame.data[1][iu[0] + 1] = codebook->u;
  199. s->frame.data[2][iv[0] + 1] = codebook->v;
  200. }
  201. codebook = &strip->v4_codebook[*data++];
  202. s->frame.data[0][iy[2] + 0] = codebook->y0;
  203. s->frame.data[0][iy[2] + 1] = codebook->y1;
  204. s->frame.data[0][iy[3] + 0] = codebook->y2;
  205. s->frame.data[0][iy[3] + 1] = codebook->y3;
  206. if (!s->palette_video) {
  207. s->frame.data[1][iu[1]] = codebook->u;
  208. s->frame.data[2][iv[1]] = codebook->v;
  209. }
  210. codebook = &strip->v4_codebook[*data++];
  211. s->frame.data[0][iy[2] + 2] = codebook->y0;
  212. s->frame.data[0][iy[2] + 3] = codebook->y1;
  213. s->frame.data[0][iy[3] + 2] = codebook->y2;
  214. s->frame.data[0][iy[3] + 3] = codebook->y3;
  215. if (!s->palette_video) {
  216. s->frame.data[1][iu[1] + 1] = codebook->u;
  217. s->frame.data[2][iv[1] + 1] = codebook->v;
  218. }
  219. }
  220. } else {
  221. /* copy from the previous frame */
  222. for (i = 0; i < 4; i++) {
  223. for (j = 0; j < 4; j++) {
  224. s->frame.data[0][iy[i] + j] =
  225. s->prev_frame.data[0][iy[i] + j];
  226. }
  227. }
  228. for (i = 0; i < 2; i++) {
  229. for (j = 0; j < 2; j++) {
  230. s->frame.data[1][iu[i] + j] =
  231. s->prev_frame.data[1][iu[i] + j];
  232. s->frame.data[2][iv[i] + j] =
  233. s->prev_frame.data[2][iv[i] + j];
  234. }
  235. }
  236. }
  237. iy[0] += 4; iy[1] += 4;
  238. iy[2] += 4; iy[3] += 4;
  239. iu[0] += 2; iu[1] += 2;
  240. iv[0] += 2; iv[1] += 2;
  241. }
  242. }
  243. return 0;
  244. }
  245. static int cinepak_decode_strip (CinepakContext *s,
  246. cvid_strip_t *strip, uint8_t *data, int size)
  247. {
  248. uint8_t *eod = (data + size);
  249. int chunk_id, chunk_size;
  250. /* coordinate sanity checks */
  251. if (strip->x1 >= s->width || strip->x2 > s->width ||
  252. strip->y1 >= s->height || strip->y2 > s->height ||
  253. strip->x1 >= strip->x2 || strip->y1 >= strip->y2)
  254. return -1;
  255. while ((data + 4) <= eod) {
  256. chunk_id = BE_16 (&data[0]);
  257. chunk_size = BE_16 (&data[2]) - 4;
  258. data += 4;
  259. chunk_size = ((data + chunk_size) > eod) ? (eod - data) : chunk_size;
  260. switch (chunk_id) {
  261. case 0x2000:
  262. case 0x2100:
  263. case 0x2400:
  264. case 0x2500:
  265. cinepak_decode_codebook (strip->v4_codebook, chunk_id,
  266. chunk_size, data);
  267. break;
  268. case 0x2200:
  269. case 0x2300:
  270. case 0x2600:
  271. case 0x2700:
  272. cinepak_decode_codebook (strip->v1_codebook, chunk_id,
  273. chunk_size, data);
  274. break;
  275. case 0x3000:
  276. case 0x3100:
  277. case 0x3200:
  278. return cinepak_decode_vectors (s, strip, chunk_id,
  279. chunk_size, data);
  280. }
  281. data += chunk_size;
  282. }
  283. return -1;
  284. }
  285. static int cinepak_decode (CinepakContext *s)
  286. {
  287. uint8_t *eod = (s->data + s->size);
  288. int i, result, strip_size, frame_flags, num_strips;
  289. int y0 = 0;
  290. if (s->size < 10)
  291. return -1;
  292. frame_flags = s->data[0];
  293. num_strips = BE_16 (&s->data[8]);
  294. s->data += 10;
  295. if (num_strips > MAX_STRIPS)
  296. num_strips = MAX_STRIPS;
  297. for (i=0; i < num_strips; i++) {
  298. if ((s->data + 12) > eod)
  299. return -1;
  300. s->strips[i].id = BE_16 (s->data);
  301. s->strips[i].y1 = y0;
  302. s->strips[i].x1 = 0;
  303. s->strips[i].y2 = y0 + BE_16 (&s->data[8]);
  304. s->strips[i].x2 = s->avctx->width;
  305. strip_size = BE_16 (&s->data[2]) - 12;
  306. s->data += 12;
  307. strip_size = ((s->data + strip_size) > eod) ? (eod - s->data) : strip_size;
  308. if ((i > 0) && !(frame_flags & 0x01)) {
  309. memcpy (s->strips[i].v4_codebook, s->strips[i-1].v4_codebook,
  310. sizeof(s->strips[i].v4_codebook));
  311. memcpy (s->strips[i].v1_codebook, s->strips[i-1].v1_codebook,
  312. sizeof(s->strips[i].v1_codebook));
  313. }
  314. result = cinepak_decode_strip (s, &s->strips[i], s->data, strip_size);
  315. if (result != 0)
  316. return result;
  317. s->data += strip_size;
  318. y0 = s->strips[i].y2;
  319. }
  320. return 0;
  321. }
  322. static int cinepak_decode_init(AVCodecContext *avctx)
  323. {
  324. CinepakContext *s = (CinepakContext *)avctx->priv_data;
  325. /*
  326. int i;
  327. unsigned char r, g, b;
  328. unsigned char *raw_palette;
  329. unsigned int *palette32;
  330. */
  331. s->avctx = avctx;
  332. s->width = (avctx->width + 3) & ~3;
  333. s->height = (avctx->height + 3) & ~3;
  334. // check for paletted data
  335. s->palette_video = 0;
  336. avctx->pix_fmt = PIX_FMT_YUV420P;
  337. avctx->has_b_frames = 0;
  338. dsputil_init(&s->dsp, avctx);
  339. s->frame.data[0] = s->prev_frame.data[0] = NULL;
  340. return 0;
  341. }
  342. static int cinepak_decode_frame(AVCodecContext *avctx,
  343. void *data, int *data_size,
  344. uint8_t *buf, int buf_size)
  345. {
  346. CinepakContext *s = (CinepakContext *)avctx->priv_data;
  347. s->data = buf;
  348. s->size = buf_size;
  349. if (avctx->get_buffer(avctx, &s->frame)) {
  350. av_log(avctx, AV_LOG_ERROR, " Cinepak: get_buffer() failed\n");
  351. return -1;
  352. }
  353. cinepak_decode(s);
  354. if (s->prev_frame.data[0])
  355. avctx->release_buffer(avctx, &s->prev_frame);
  356. /* shuffle frames */
  357. s->prev_frame = s->frame;
  358. *data_size = sizeof(AVFrame);
  359. *(AVFrame*)data = s->frame;
  360. /* report that the buffer was completely consumed */
  361. return buf_size;
  362. }
  363. static int cinepak_decode_end(AVCodecContext *avctx)
  364. {
  365. CinepakContext *s = (CinepakContext *)avctx->priv_data;
  366. if (s->prev_frame.data[0])
  367. avctx->release_buffer(avctx, &s->prev_frame);
  368. return 0;
  369. }
  370. AVCodec cinepak_decoder = {
  371. "cinepak",
  372. CODEC_TYPE_VIDEO,
  373. CODEC_ID_CINEPAK,
  374. sizeof(CinepakContext),
  375. cinepak_decode_init,
  376. NULL,
  377. cinepak_decode_end,
  378. cinepak_decode_frame,
  379. CODEC_CAP_DR1,
  380. };