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.

468 lines
15KB

  1. /*
  2. * Sierra VMD video decoder
  3. *
  4. * This file is part of Libav.
  5. *
  6. * Libav is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU Lesser General Public
  8. * License as published by the Free Software Foundation; either
  9. * version 2.1 of the License, or (at your option) any later version.
  10. *
  11. * Libav is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public
  17. * License along with Libav; if not, write to the Free Software
  18. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  19. */
  20. /**
  21. * @file
  22. * Sierra VMD video decoder
  23. * by Vladimir "VAG" Gneushev (vagsoft at mail.ru)
  24. * for more information on the Sierra VMD format, visit:
  25. * http://www.pcisys.net/~melanson/codecs/
  26. *
  27. * The video decoder outputs PAL8 colorspace data. The decoder expects
  28. * a 0x330-byte VMD file header to be transmitted via extradata during
  29. * codec initialization. Each encoded frame that is sent to this decoder
  30. * is expected to be prepended with the appropriate 16-byte frame
  31. * information record from the VMD file.
  32. */
  33. #include <string.h>
  34. #include "libavutil/common.h"
  35. #include "libavutil/intreadwrite.h"
  36. #include "avcodec.h"
  37. #include "internal.h"
  38. #include "bytestream.h"
  39. #define VMD_HEADER_SIZE 0x330
  40. #define PALETTE_COUNT 256
  41. typedef struct VmdVideoContext {
  42. AVCodecContext *avctx;
  43. AVFrame *prev_frame;
  44. const unsigned char *buf;
  45. int size;
  46. unsigned char palette[PALETTE_COUNT * 4];
  47. unsigned char *unpack_buffer;
  48. int unpack_buffer_size;
  49. int x_off, y_off;
  50. } VmdVideoContext;
  51. #define QUEUE_SIZE 0x1000
  52. #define QUEUE_MASK 0x0FFF
  53. static void lz_unpack(const unsigned char *src, int src_len,
  54. unsigned char *dest, int dest_len)
  55. {
  56. unsigned char *d;
  57. unsigned char *d_end;
  58. unsigned char queue[QUEUE_SIZE];
  59. unsigned int qpos;
  60. unsigned int dataleft;
  61. unsigned int chainofs;
  62. unsigned int chainlen;
  63. unsigned int speclen;
  64. unsigned char tag;
  65. unsigned int i, j;
  66. GetByteContext gb;
  67. bytestream2_init(&gb, src, src_len);
  68. d = dest;
  69. d_end = d + dest_len;
  70. dataleft = bytestream2_get_le32(&gb);
  71. memset(queue, 0x20, QUEUE_SIZE);
  72. if (bytestream2_get_bytes_left(&gb) < 4)
  73. return;
  74. if (bytestream2_peek_le32(&gb) == 0x56781234) {
  75. bytestream2_get_le32(&gb);
  76. qpos = 0x111;
  77. speclen = 0xF + 3;
  78. } else {
  79. qpos = 0xFEE;
  80. speclen = 100; /* no speclen */
  81. }
  82. while (dataleft > 0 && bytestream2_get_bytes_left(&gb) > 0) {
  83. tag = bytestream2_get_byteu(&gb);
  84. if ((tag == 0xFF) && (dataleft > 8)) {
  85. if (d + 8 > d_end || bytestream2_get_bytes_left(&gb) < 8)
  86. return;
  87. for (i = 0; i < 8; i++) {
  88. queue[qpos++] = *d++ = bytestream2_get_byteu(&gb);
  89. qpos &= QUEUE_MASK;
  90. }
  91. dataleft -= 8;
  92. } else {
  93. for (i = 0; i < 8; i++) {
  94. if (dataleft == 0)
  95. break;
  96. if (tag & 0x01) {
  97. if (d + 1 > d_end || bytestream2_get_bytes_left(&gb) < 1)
  98. return;
  99. queue[qpos++] = *d++ = bytestream2_get_byte(&gb);
  100. qpos &= QUEUE_MASK;
  101. dataleft--;
  102. } else {
  103. chainofs = bytestream2_get_byte(&gb);
  104. chainofs |= ((bytestream2_peek_byte(&gb) & 0xF0) << 4);
  105. chainlen = (bytestream2_get_byte(&gb) & 0x0F) + 3;
  106. if (chainlen == speclen) {
  107. chainlen = bytestream2_get_byte(&gb) + 0xF + 3;
  108. }
  109. if (d + chainlen > d_end)
  110. return;
  111. for (j = 0; j < chainlen; j++) {
  112. *d = queue[chainofs++ & QUEUE_MASK];
  113. queue[qpos++] = *d++;
  114. qpos &= QUEUE_MASK;
  115. }
  116. dataleft -= chainlen;
  117. }
  118. tag >>= 1;
  119. }
  120. }
  121. }
  122. }
  123. static int rle_unpack(const unsigned char *src, unsigned char *dest,
  124. int src_count, int src_size, int dest_len)
  125. {
  126. unsigned char *pd;
  127. int i, l, used = 0;
  128. unsigned char *dest_end = dest + dest_len;
  129. GetByteContext gb;
  130. uint16_t run_val;
  131. bytestream2_init(&gb, src, src_size);
  132. pd = dest;
  133. if (src_count & 1) {
  134. if (bytestream2_get_bytes_left(&gb) < 1)
  135. return 0;
  136. *pd++ = bytestream2_get_byteu(&gb);
  137. used++;
  138. }
  139. do {
  140. if (bytestream2_get_bytes_left(&gb) < 1)
  141. break;
  142. l = bytestream2_get_byteu(&gb);
  143. if (l & 0x80) {
  144. l = (l & 0x7F) * 2;
  145. if (pd + l > dest_end || bytestream2_get_bytes_left(&gb) < l)
  146. return bytestream2_tell(&gb);
  147. bytestream2_get_buffer(&gb, pd, l);
  148. pd += l;
  149. } else {
  150. if (pd + l > dest_end || bytestream2_get_bytes_left(&gb) < 2)
  151. return bytestream2_tell(&gb);
  152. run_val = bytestream2_get_ne16(&gb);
  153. for (i = 0; i < l; i++) {
  154. AV_WN16(pd, run_val);
  155. pd += 2;
  156. }
  157. l *= 2;
  158. }
  159. used += l;
  160. } while (used < src_count);
  161. return bytestream2_tell(&gb);
  162. }
  163. static int vmd_decode(VmdVideoContext *s, AVFrame *frame)
  164. {
  165. int i;
  166. unsigned int *palette32;
  167. unsigned char r, g, b;
  168. GetByteContext gb;
  169. unsigned char meth;
  170. unsigned char *dp; /* pointer to current frame */
  171. unsigned char *pp; /* pointer to previous frame */
  172. unsigned char len;
  173. int ofs;
  174. int frame_x, frame_y;
  175. int frame_width, frame_height;
  176. frame_x = AV_RL16(&s->buf[6]);
  177. frame_y = AV_RL16(&s->buf[8]);
  178. frame_width = AV_RL16(&s->buf[10]) - frame_x + 1;
  179. frame_height = AV_RL16(&s->buf[12]) - frame_y + 1;
  180. if (frame_x < 0 || frame_width < 0 ||
  181. frame_x >= s->avctx->width ||
  182. frame_width > s->avctx->width ||
  183. frame_x + frame_width > s->avctx->width) {
  184. av_log(s->avctx, AV_LOG_ERROR,
  185. "Invalid horizontal range %d-%d\n",
  186. frame_x, frame_width);
  187. return AVERROR_INVALIDDATA;
  188. }
  189. if (frame_y < 0 || frame_height < 0 ||
  190. frame_y >= s->avctx->height ||
  191. frame_height > s->avctx->height ||
  192. frame_y + frame_height > s->avctx->height) {
  193. av_log(s->avctx, AV_LOG_ERROR,
  194. "Invalid vertical range %d-%d\n",
  195. frame_x, frame_width);
  196. return AVERROR_INVALIDDATA;
  197. }
  198. if ((frame_width == s->avctx->width && frame_height == s->avctx->height) &&
  199. (frame_x || frame_y)) {
  200. s->x_off = frame_x;
  201. s->y_off = frame_y;
  202. }
  203. frame_x -= s->x_off;
  204. frame_y -= s->y_off;
  205. /* if only a certain region will be updated, copy the entire previous
  206. * frame before the decode */
  207. if (s->prev_frame->data[0] &&
  208. (frame_x || frame_y || (frame_width != s->avctx->width) ||
  209. (frame_height != s->avctx->height))) {
  210. memcpy(frame->data[0], s->prev_frame->data[0],
  211. s->avctx->height * frame->linesize[0]);
  212. }
  213. /* check if there is a new palette */
  214. bytestream2_init(&gb, s->buf + 16, s->size - 16);
  215. if (s->buf[15] & 0x02) {
  216. bytestream2_skip(&gb, 2);
  217. palette32 = (unsigned int *)s->palette;
  218. if (bytestream2_get_bytes_left(&gb) >= PALETTE_COUNT * 3) {
  219. for (i = 0; i < PALETTE_COUNT; i++) {
  220. r = bytestream2_get_byteu(&gb) * 4;
  221. g = bytestream2_get_byteu(&gb) * 4;
  222. b = bytestream2_get_byteu(&gb) * 4;
  223. palette32[i] = (r << 16) | (g << 8) | (b);
  224. }
  225. } else {
  226. av_log(s->avctx, AV_LOG_ERROR, "Incomplete palette\n");
  227. return AVERROR_INVALIDDATA;
  228. }
  229. s->size -= PALETTE_COUNT * 3 + 2;
  230. }
  231. if (!s->size)
  232. return 0;
  233. /* originally UnpackFrame in VAG's code */
  234. if (bytestream2_get_bytes_left(&gb) < 1)
  235. return AVERROR_INVALIDDATA;
  236. meth = bytestream2_get_byteu(&gb);
  237. if (meth & 0x80) {
  238. if (!s->unpack_buffer_size) {
  239. av_log(s->avctx, AV_LOG_ERROR,
  240. "Trying to unpack LZ-compressed frame with no LZ buffer\n");
  241. return AVERROR_INVALIDDATA;
  242. }
  243. lz_unpack(gb.buffer, bytestream2_get_bytes_left(&gb),
  244. s->unpack_buffer, s->unpack_buffer_size);
  245. meth &= 0x7F;
  246. bytestream2_init(&gb, s->unpack_buffer, s->unpack_buffer_size);
  247. }
  248. dp = &frame->data[0][frame_y * frame->linesize[0] + frame_x];
  249. pp = &s->prev_frame->data[0][frame_y * s->prev_frame->linesize[0] + frame_x];
  250. switch (meth) {
  251. case 1:
  252. for (i = 0; i < frame_height; i++) {
  253. ofs = 0;
  254. do {
  255. len = bytestream2_get_byte(&gb);
  256. if (len & 0x80) {
  257. len = (len & 0x7F) + 1;
  258. if (ofs + len > frame_width ||
  259. bytestream2_get_bytes_left(&gb) < len)
  260. return AVERROR_INVALIDDATA;
  261. bytestream2_get_buffer(&gb, &dp[ofs], len);
  262. ofs += len;
  263. } else {
  264. /* interframe pixel copy */
  265. if (ofs + len + 1 > frame_width || !s->prev_frame->data[0])
  266. return AVERROR_INVALIDDATA;
  267. memcpy(&dp[ofs], &pp[ofs], len + 1);
  268. ofs += len + 1;
  269. }
  270. } while (ofs < frame_width);
  271. if (ofs > frame_width) {
  272. av_log(s->avctx, AV_LOG_ERROR,
  273. "VMD video: offset > width (%d > %d)\n",
  274. ofs, frame_width);
  275. return AVERROR_INVALIDDATA;
  276. }
  277. dp += frame->linesize[0];
  278. pp += s->prev_frame->linesize[0];
  279. }
  280. break;
  281. case 2:
  282. for (i = 0; i < frame_height; i++) {
  283. bytestream2_get_buffer(&gb, dp, frame_width);
  284. dp += frame->linesize[0];
  285. pp += s->prev_frame->linesize[0];
  286. }
  287. break;
  288. case 3:
  289. for (i = 0; i < frame_height; i++) {
  290. ofs = 0;
  291. do {
  292. len = bytestream2_get_byte(&gb);
  293. if (len & 0x80) {
  294. len = (len & 0x7F) + 1;
  295. if (bytestream2_peek_byte(&gb) == 0xFF) {
  296. int slen = len;
  297. bytestream2_get_byte(&gb);
  298. len = rle_unpack(gb.buffer, &dp[ofs],
  299. len, bytestream2_get_bytes_left(&gb),
  300. frame_width - ofs);
  301. ofs += slen;
  302. bytestream2_skip(&gb, len);
  303. } else {
  304. bytestream2_get_buffer(&gb, &dp[ofs], len);
  305. ofs += len;
  306. }
  307. } else {
  308. /* interframe pixel copy */
  309. if (ofs + len + 1 > frame_width || !s->prev_frame->data[0])
  310. return AVERROR_INVALIDDATA;
  311. memcpy(&dp[ofs], &pp[ofs], len + 1);
  312. ofs += len + 1;
  313. }
  314. } while (ofs < frame_width);
  315. if (ofs > frame_width) {
  316. av_log(s->avctx, AV_LOG_ERROR,
  317. "VMD video: offset > width (%d > %d)\n",
  318. ofs, frame_width);
  319. return AVERROR_INVALIDDATA;
  320. }
  321. dp += frame->linesize[0];
  322. pp += s->prev_frame->linesize[0];
  323. }
  324. break;
  325. }
  326. return 0;
  327. }
  328. static av_cold int vmdvideo_decode_end(AVCodecContext *avctx)
  329. {
  330. VmdVideoContext *s = avctx->priv_data;
  331. av_frame_free(&s->prev_frame);
  332. av_free(s->unpack_buffer);
  333. return 0;
  334. }
  335. static av_cold int vmdvideo_decode_init(AVCodecContext *avctx)
  336. {
  337. VmdVideoContext *s = avctx->priv_data;
  338. int i;
  339. unsigned int *palette32;
  340. int palette_index = 0;
  341. unsigned char r, g, b;
  342. unsigned char *vmd_header;
  343. unsigned char *raw_palette;
  344. s->avctx = avctx;
  345. avctx->pix_fmt = AV_PIX_FMT_PAL8;
  346. /* make sure the VMD header made it */
  347. if (s->avctx->extradata_size != VMD_HEADER_SIZE) {
  348. av_log(s->avctx, AV_LOG_ERROR, "VMD video: expected extradata size of %d\n",
  349. VMD_HEADER_SIZE);
  350. return -1;
  351. }
  352. vmd_header = (unsigned char *)avctx->extradata;
  353. s->unpack_buffer_size = AV_RL32(&vmd_header[800]);
  354. if (s->unpack_buffer_size) {
  355. s->unpack_buffer = av_malloc(s->unpack_buffer_size);
  356. if (!s->unpack_buffer)
  357. return AVERROR(ENOMEM);
  358. }
  359. /* load up the initial palette */
  360. raw_palette = &vmd_header[28];
  361. palette32 = (unsigned int *)s->palette;
  362. for (i = 0; i < PALETTE_COUNT; i++) {
  363. r = raw_palette[palette_index++] * 4;
  364. g = raw_palette[palette_index++] * 4;
  365. b = raw_palette[palette_index++] * 4;
  366. palette32[i] = (r << 16) | (g << 8) | (b);
  367. }
  368. s->prev_frame = av_frame_alloc();
  369. if (!s->prev_frame) {
  370. vmdvideo_decode_end(avctx);
  371. return AVERROR(ENOMEM);
  372. }
  373. return 0;
  374. }
  375. static int vmdvideo_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. VmdVideoContext *s = avctx->priv_data;
  382. AVFrame *frame = data;
  383. int ret;
  384. s->buf = buf;
  385. s->size = buf_size;
  386. if (buf_size < 16)
  387. return AVERROR_INVALIDDATA;
  388. if ((ret = ff_get_buffer(avctx, frame, AV_GET_BUFFER_FLAG_REF)) < 0) {
  389. av_log(s->avctx, AV_LOG_ERROR, "VMD Video: get_buffer() failed\n");
  390. return ret;
  391. }
  392. if ((ret = vmd_decode(s, frame)) < 0)
  393. return ret;
  394. /* make the palette available on the way out */
  395. memcpy(frame->data[1], s->palette, PALETTE_COUNT * 4);
  396. /* shuffle frames */
  397. av_frame_unref(s->prev_frame);
  398. if ((ret = av_frame_ref(s->prev_frame, frame)) < 0)
  399. return ret;
  400. *got_frame = 1;
  401. /* report that the buffer was completely consumed */
  402. return buf_size;
  403. }
  404. AVCodec ff_vmdvideo_decoder = {
  405. .name = "vmdvideo",
  406. .long_name = NULL_IF_CONFIG_SMALL("Sierra VMD video"),
  407. .type = AVMEDIA_TYPE_VIDEO,
  408. .id = AV_CODEC_ID_VMDVIDEO,
  409. .priv_data_size = sizeof(VmdVideoContext),
  410. .init = vmdvideo_decode_init,
  411. .close = vmdvideo_decode_end,
  412. .decode = vmdvideo_decode_frame,
  413. .capabilities = AV_CODEC_CAP_DR1,
  414. };