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.

487 lines
16KB

  1. /*
  2. * Cinepak 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
  23. * Cinepak video decoder
  24. * @author Ewald Snel <ewald@rambo.its.tudelft.nl>
  25. *
  26. * @see For more information on the Cinepak algorithm, visit:
  27. * http://www.csse.monash.edu.au/~timf/
  28. * @see For more information on the quirky data inside Sega FILM/CPK files, visit:
  29. * http://wiki.multimedia.cx/index.php?title=Sega_FILM
  30. */
  31. #include <stdio.h>
  32. #include <stdlib.h>
  33. #include <string.h>
  34. #include "libavutil/common.h"
  35. #include "libavutil/intreadwrite.h"
  36. #include "avcodec.h"
  37. typedef struct {
  38. uint8_t y0, y1, y2, y3;
  39. uint8_t u, v;
  40. } cvid_codebook;
  41. #define MAX_STRIPS 32
  42. typedef struct {
  43. uint16_t id;
  44. uint16_t x1, y1;
  45. uint16_t x2, y2;
  46. cvid_codebook v4_codebook[256];
  47. cvid_codebook v1_codebook[256];
  48. } cvid_strip;
  49. typedef struct CinepakContext {
  50. AVCodecContext *avctx;
  51. AVFrame frame;
  52. const unsigned char *data;
  53. int size;
  54. int width, height;
  55. int palette_video;
  56. cvid_strip strips[MAX_STRIPS];
  57. int sega_film_skip_bytes;
  58. uint32_t pal[256];
  59. } CinepakContext;
  60. static void cinepak_decode_codebook (cvid_codebook *codebook,
  61. int chunk_id, int size, const uint8_t *data)
  62. {
  63. const uint8_t *eod = (data + size);
  64. uint32_t flag, mask;
  65. int i, n;
  66. /* check if this chunk contains 4- or 6-element vectors */
  67. n = (chunk_id & 0x04) ? 4 : 6;
  68. flag = 0;
  69. mask = 0;
  70. for (i=0; i < 256; i++) {
  71. if ((chunk_id & 0x01) && !(mask >>= 1)) {
  72. if ((data + 4) > eod)
  73. break;
  74. flag = AV_RB32 (data);
  75. data += 4;
  76. mask = 0x80000000;
  77. }
  78. if (!(chunk_id & 0x01) || (flag & mask)) {
  79. if ((data + n) > eod)
  80. break;
  81. if (n == 6) {
  82. codebook[i].y0 = *data++;
  83. codebook[i].y1 = *data++;
  84. codebook[i].y2 = *data++;
  85. codebook[i].y3 = *data++;
  86. codebook[i].u = 128 + *data++;
  87. codebook[i].v = 128 + *data++;
  88. } else {
  89. /* this codebook type indicates either greyscale or
  90. * palettized video; if palettized, U & V components will
  91. * not be used so it is safe to set them to 128 for the
  92. * benefit of greyscale rendering in YUV420P */
  93. codebook[i].y0 = *data++;
  94. codebook[i].y1 = *data++;
  95. codebook[i].y2 = *data++;
  96. codebook[i].y3 = *data++;
  97. codebook[i].u = 128;
  98. codebook[i].v = 128;
  99. }
  100. }
  101. }
  102. }
  103. static int cinepak_decode_vectors (CinepakContext *s, cvid_strip *strip,
  104. int chunk_id, int size, const uint8_t *data)
  105. {
  106. const uint8_t *eod = (data + size);
  107. uint32_t flag, mask;
  108. cvid_codebook *codebook;
  109. unsigned int x, y;
  110. uint32_t iy[4];
  111. uint32_t iu[2];
  112. uint32_t iv[2];
  113. flag = 0;
  114. mask = 0;
  115. for (y=strip->y1; y < strip->y2; y+=4) {
  116. iy[0] = strip->x1 + (y * s->frame.linesize[0]);
  117. iy[1] = iy[0] + s->frame.linesize[0];
  118. iy[2] = iy[1] + s->frame.linesize[0];
  119. iy[3] = iy[2] + s->frame.linesize[0];
  120. iu[0] = (strip->x1/2) + ((y/2) * s->frame.linesize[1]);
  121. iu[1] = iu[0] + s->frame.linesize[1];
  122. iv[0] = (strip->x1/2) + ((y/2) * s->frame.linesize[2]);
  123. iv[1] = iv[0] + s->frame.linesize[2];
  124. for (x=strip->x1; x < strip->x2; x+=4) {
  125. if ((chunk_id & 0x01) && !(mask >>= 1)) {
  126. if ((data + 4) > eod)
  127. return AVERROR_INVALIDDATA;
  128. flag = AV_RB32 (data);
  129. data += 4;
  130. mask = 0x80000000;
  131. }
  132. if (!(chunk_id & 0x01) || (flag & mask)) {
  133. if (!(chunk_id & 0x02) && !(mask >>= 1)) {
  134. if ((data + 4) > eod)
  135. return AVERROR_INVALIDDATA;
  136. flag = AV_RB32 (data);
  137. data += 4;
  138. mask = 0x80000000;
  139. }
  140. if ((chunk_id & 0x02) || (~flag & mask)) {
  141. if (data >= eod)
  142. return AVERROR_INVALIDDATA;
  143. codebook = &strip->v1_codebook[*data++];
  144. s->frame.data[0][iy[0] + 0] = codebook->y0;
  145. s->frame.data[0][iy[0] + 1] = codebook->y0;
  146. s->frame.data[0][iy[1] + 0] = codebook->y0;
  147. s->frame.data[0][iy[1] + 1] = codebook->y0;
  148. if (!s->palette_video) {
  149. s->frame.data[1][iu[0]] = codebook->u;
  150. s->frame.data[2][iv[0]] = codebook->v;
  151. }
  152. s->frame.data[0][iy[0] + 2] = codebook->y1;
  153. s->frame.data[0][iy[0] + 3] = codebook->y1;
  154. s->frame.data[0][iy[1] + 2] = codebook->y1;
  155. s->frame.data[0][iy[1] + 3] = codebook->y1;
  156. if (!s->palette_video) {
  157. s->frame.data[1][iu[0] + 1] = codebook->u;
  158. s->frame.data[2][iv[0] + 1] = codebook->v;
  159. }
  160. s->frame.data[0][iy[2] + 0] = codebook->y2;
  161. s->frame.data[0][iy[2] + 1] = codebook->y2;
  162. s->frame.data[0][iy[3] + 0] = codebook->y2;
  163. s->frame.data[0][iy[3] + 1] = codebook->y2;
  164. if (!s->palette_video) {
  165. s->frame.data[1][iu[1]] = codebook->u;
  166. s->frame.data[2][iv[1]] = codebook->v;
  167. }
  168. s->frame.data[0][iy[2] + 2] = codebook->y3;
  169. s->frame.data[0][iy[2] + 3] = codebook->y3;
  170. s->frame.data[0][iy[3] + 2] = codebook->y3;
  171. s->frame.data[0][iy[3] + 3] = codebook->y3;
  172. if (!s->palette_video) {
  173. s->frame.data[1][iu[1] + 1] = codebook->u;
  174. s->frame.data[2][iv[1] + 1] = codebook->v;
  175. }
  176. } else if (flag & mask) {
  177. if ((data + 4) > eod)
  178. return AVERROR_INVALIDDATA;
  179. codebook = &strip->v4_codebook[*data++];
  180. s->frame.data[0][iy[0] + 0] = codebook->y0;
  181. s->frame.data[0][iy[0] + 1] = codebook->y1;
  182. s->frame.data[0][iy[1] + 0] = codebook->y2;
  183. s->frame.data[0][iy[1] + 1] = codebook->y3;
  184. if (!s->palette_video) {
  185. s->frame.data[1][iu[0]] = codebook->u;
  186. s->frame.data[2][iv[0]] = codebook->v;
  187. }
  188. codebook = &strip->v4_codebook[*data++];
  189. s->frame.data[0][iy[0] + 2] = codebook->y0;
  190. s->frame.data[0][iy[0] + 3] = codebook->y1;
  191. s->frame.data[0][iy[1] + 2] = codebook->y2;
  192. s->frame.data[0][iy[1] + 3] = codebook->y3;
  193. if (!s->palette_video) {
  194. s->frame.data[1][iu[0] + 1] = codebook->u;
  195. s->frame.data[2][iv[0] + 1] = codebook->v;
  196. }
  197. codebook = &strip->v4_codebook[*data++];
  198. s->frame.data[0][iy[2] + 0] = codebook->y0;
  199. s->frame.data[0][iy[2] + 1] = codebook->y1;
  200. s->frame.data[0][iy[3] + 0] = codebook->y2;
  201. s->frame.data[0][iy[3] + 1] = codebook->y3;
  202. if (!s->palette_video) {
  203. s->frame.data[1][iu[1]] = codebook->u;
  204. s->frame.data[2][iv[1]] = codebook->v;
  205. }
  206. codebook = &strip->v4_codebook[*data++];
  207. s->frame.data[0][iy[2] + 2] = codebook->y0;
  208. s->frame.data[0][iy[2] + 3] = codebook->y1;
  209. s->frame.data[0][iy[3] + 2] = codebook->y2;
  210. s->frame.data[0][iy[3] + 3] = codebook->y3;
  211. if (!s->palette_video) {
  212. s->frame.data[1][iu[1] + 1] = codebook->u;
  213. s->frame.data[2][iv[1] + 1] = codebook->v;
  214. }
  215. }
  216. }
  217. iy[0] += 4; iy[1] += 4;
  218. iy[2] += 4; iy[3] += 4;
  219. iu[0] += 2; iu[1] += 2;
  220. iv[0] += 2; iv[1] += 2;
  221. }
  222. }
  223. return 0;
  224. }
  225. static int cinepak_decode_strip (CinepakContext *s,
  226. cvid_strip *strip, const uint8_t *data, int size)
  227. {
  228. const uint8_t *eod = (data + size);
  229. int chunk_id, chunk_size;
  230. /* coordinate sanity checks */
  231. if (strip->x2 > s->width ||
  232. strip->y2 > s->height ||
  233. strip->x1 >= strip->x2 || strip->y1 >= strip->y2)
  234. return AVERROR_INVALIDDATA;
  235. while ((data + 4) <= eod) {
  236. chunk_id = data[0];
  237. chunk_size = AV_RB24 (&data[1]) - 4;
  238. if(chunk_size < 0)
  239. return AVERROR_INVALIDDATA;
  240. data += 4;
  241. chunk_size = ((data + chunk_size) > eod) ? (eod - data) : chunk_size;
  242. switch (chunk_id) {
  243. case 0x20:
  244. case 0x21:
  245. case 0x24:
  246. case 0x25:
  247. cinepak_decode_codebook (strip->v4_codebook, chunk_id,
  248. chunk_size, data);
  249. break;
  250. case 0x22:
  251. case 0x23:
  252. case 0x26:
  253. case 0x27:
  254. cinepak_decode_codebook (strip->v1_codebook, chunk_id,
  255. chunk_size, data);
  256. break;
  257. case 0x30:
  258. case 0x31:
  259. case 0x32:
  260. return cinepak_decode_vectors (s, strip, chunk_id,
  261. chunk_size, data);
  262. }
  263. data += chunk_size;
  264. }
  265. return AVERROR_INVALIDDATA;
  266. }
  267. static int cinepak_decode (CinepakContext *s)
  268. {
  269. const uint8_t *eod = (s->data + s->size);
  270. int i, result, strip_size, frame_flags, num_strips;
  271. int y0 = 0;
  272. int encoded_buf_size;
  273. if (s->size < 10)
  274. return AVERROR_INVALIDDATA;
  275. frame_flags = s->data[0];
  276. num_strips = AV_RB16 (&s->data[8]);
  277. encoded_buf_size = AV_RB24(&s->data[1]);
  278. /* if this is the first frame, check for deviant Sega FILM data */
  279. if (s->sega_film_skip_bytes == -1) {
  280. if (!encoded_buf_size) {
  281. av_log_ask_for_sample(s->avctx, "encoded_buf_size is 0");
  282. return AVERROR_PATCHWELCOME;
  283. }
  284. if (encoded_buf_size != s->size && (s->size % encoded_buf_size) != 0) {
  285. /* If the encoded frame size differs from the frame size as indicated
  286. * by the container file, this data likely comes from a Sega FILM/CPK file.
  287. * If the frame header is followed by the bytes FE 00 00 06 00 00 then
  288. * this is probably one of the two known files that have 6 extra bytes
  289. * after the frame header. Else, assume 2 extra bytes. The container
  290. * size also cannot be a multiple of the encoded size. */
  291. if (s->size >= 16 &&
  292. (s->data[10] == 0xFE) &&
  293. (s->data[11] == 0x00) &&
  294. (s->data[12] == 0x00) &&
  295. (s->data[13] == 0x06) &&
  296. (s->data[14] == 0x00) &&
  297. (s->data[15] == 0x00))
  298. s->sega_film_skip_bytes = 6;
  299. else
  300. s->sega_film_skip_bytes = 2;
  301. } else
  302. s->sega_film_skip_bytes = 0;
  303. }
  304. s->data += 10 + s->sega_film_skip_bytes;
  305. num_strips = FFMIN(num_strips, MAX_STRIPS);
  306. s->frame.key_frame = 0;
  307. for (i=0; i < num_strips; i++) {
  308. if ((s->data + 12) > eod)
  309. return AVERROR_INVALIDDATA;
  310. s->strips[i].id = s->data[0];
  311. s->strips[i].y1 = y0;
  312. s->strips[i].x1 = 0;
  313. s->strips[i].y2 = y0 + AV_RB16 (&s->data[8]);
  314. s->strips[i].x2 = s->avctx->width;
  315. if (s->strips[i].id == 0x10)
  316. s->frame.key_frame = 1;
  317. strip_size = AV_RB24 (&s->data[1]) - 12;
  318. if (strip_size < 0)
  319. return AVERROR_INVALIDDATA;
  320. s->data += 12;
  321. strip_size = ((s->data + strip_size) > eod) ? (eod - s->data) : strip_size;
  322. if ((i > 0) && !(frame_flags & 0x01)) {
  323. memcpy (s->strips[i].v4_codebook, s->strips[i-1].v4_codebook,
  324. sizeof(s->strips[i].v4_codebook));
  325. memcpy (s->strips[i].v1_codebook, s->strips[i-1].v1_codebook,
  326. sizeof(s->strips[i].v1_codebook));
  327. }
  328. result = cinepak_decode_strip (s, &s->strips[i], s->data, strip_size);
  329. if (result != 0)
  330. return result;
  331. s->data += strip_size;
  332. y0 = s->strips[i].y2;
  333. }
  334. return 0;
  335. }
  336. static av_cold int cinepak_decode_init(AVCodecContext *avctx)
  337. {
  338. CinepakContext *s = avctx->priv_data;
  339. s->avctx = avctx;
  340. s->width = (avctx->width + 3) & ~3;
  341. s->height = (avctx->height + 3) & ~3;
  342. s->sega_film_skip_bytes = -1; /* uninitialized state */
  343. // check for paletted data
  344. if (avctx->bits_per_coded_sample != 8) {
  345. s->palette_video = 0;
  346. avctx->pix_fmt = AV_PIX_FMT_YUV420P;
  347. } else {
  348. s->palette_video = 1;
  349. avctx->pix_fmt = AV_PIX_FMT_PAL8;
  350. }
  351. avcodec_get_frame_defaults(&s->frame);
  352. s->frame.data[0] = NULL;
  353. return 0;
  354. }
  355. static int cinepak_decode_frame(AVCodecContext *avctx,
  356. void *data, int *got_frame,
  357. AVPacket *avpkt)
  358. {
  359. const uint8_t *buf = avpkt->data;
  360. int ret = 0, buf_size = avpkt->size;
  361. CinepakContext *s = avctx->priv_data;
  362. s->data = buf;
  363. s->size = buf_size;
  364. s->frame.reference = 3;
  365. s->frame.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE |
  366. FF_BUFFER_HINTS_REUSABLE;
  367. if ((ret = avctx->reget_buffer(avctx, &s->frame))) {
  368. av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
  369. return ret;
  370. }
  371. if (s->palette_video) {
  372. const uint8_t *pal = av_packet_get_side_data(avpkt, AV_PKT_DATA_PALETTE, NULL);
  373. if (pal) {
  374. s->frame.palette_has_changed = 1;
  375. memcpy(s->pal, pal, AVPALETTE_SIZE);
  376. }
  377. }
  378. cinepak_decode(s);
  379. if (s->palette_video)
  380. memcpy (s->frame.data[1], s->pal, AVPALETTE_SIZE);
  381. *got_frame = 1;
  382. *(AVFrame*)data = s->frame;
  383. /* report that the buffer was completely consumed */
  384. return buf_size;
  385. }
  386. static av_cold int cinepak_decode_end(AVCodecContext *avctx)
  387. {
  388. CinepakContext *s = avctx->priv_data;
  389. if (s->frame.data[0])
  390. avctx->release_buffer(avctx, &s->frame);
  391. return 0;
  392. }
  393. AVCodec ff_cinepak_decoder = {
  394. .name = "cinepak",
  395. .type = AVMEDIA_TYPE_VIDEO,
  396. .id = AV_CODEC_ID_CINEPAK,
  397. .priv_data_size = sizeof(CinepakContext),
  398. .init = cinepak_decode_init,
  399. .close = cinepak_decode_end,
  400. .decode = cinepak_decode_frame,
  401. .capabilities = CODEC_CAP_DR1,
  402. .long_name = NULL_IF_CONFIG_SMALL("Cinepak"),
  403. };