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.

170 lines
4.2KB

  1. /*
  2. * Winnov WNV1 codec
  3. * Copyright (c) 2005 Konstantin Shishkov
  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 wnv1.c
  22. * Winnov WNV1 codec.
  23. */
  24. #include "avcodec.h"
  25. #include "common.h"
  26. typedef struct WNV1Context{
  27. AVCodecContext *avctx;
  28. AVFrame pic;
  29. int shift;
  30. /* bit buffer */
  31. unsigned long bitbuf;
  32. int bits;
  33. uint8_t *buf;
  34. } WNV1Context;
  35. /* returns modified base_value */
  36. static inline int wnv1_get_code(WNV1Context *w, int base_value)
  37. {
  38. int v = 0;
  39. if (w->bits < 16) { /* need to fill bit buffer */
  40. w->bitbuf |= LE_16(w->buf) << w->bits;
  41. w->buf += 2;
  42. w->bits += 16;
  43. }
  44. /* escape code */
  45. if ((w->bitbuf & 0xFF) == 0xFF) {
  46. w->bitbuf >>= 8;
  47. w->bits -= 8;
  48. if (w->bits < 16) { /* need to fill bit buffer */
  49. w->bitbuf |= LE_16(w->buf) << w->bits;
  50. w->buf += 2;
  51. w->bits += 16;
  52. }
  53. v = w->bitbuf & (0xFF >> w->shift);
  54. w->bitbuf >>= 8 - w->shift;
  55. w->bits -= 8 - w->shift;
  56. return v << w->shift;
  57. }
  58. /* zero code */
  59. if (!(w->bitbuf & 1)) {
  60. w->bitbuf >>= 1;
  61. w->bits--;
  62. return base_value;
  63. }
  64. /* reversed unary code and sign */
  65. while (w->bits && w->bitbuf & 1) {
  66. w->bitbuf >>= 1;
  67. w->bits--;
  68. v++;
  69. }
  70. w->bitbuf >>= 1;
  71. w->bits--;
  72. if(w->bitbuf & 1)
  73. v = -v;
  74. w->bitbuf >>= 1;
  75. w->bits--;
  76. v <<= w->shift;
  77. return base_value + v;
  78. }
  79. static int decode_frame(AVCodecContext *avctx,
  80. void *data, int *data_size,
  81. uint8_t *buf, int buf_size)
  82. {
  83. WNV1Context * const l = avctx->priv_data;
  84. AVFrame * const p= (AVFrame*)&l->pic;
  85. unsigned char *Y,*U,*V;
  86. int i, j;
  87. int prev_y = 0, prev_u = 0, prev_v = 0;
  88. if(p->data[0])
  89. avctx->release_buffer(avctx, p);
  90. p->reference = 0;
  91. if(avctx->get_buffer(avctx, p) < 0){
  92. av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
  93. return -1;
  94. }
  95. p->key_frame = 1;
  96. l->bitbuf = 0;
  97. l->bits = 0;
  98. l->buf = buf + 8;
  99. if (buf[2] >> 4 == 6)
  100. l->shift = 2;
  101. else {
  102. l->shift = 8 - (buf[2] >> 4);
  103. if (l->shift > 4) {
  104. av_log(avctx, AV_LOG_ERROR, "Unknown WNV1 frame header value %i, please upload file for study\n", buf[2] >> 4);
  105. l->shift = 4;
  106. }
  107. if (l->shift < 1) {
  108. av_log(avctx, AV_LOG_ERROR, "Unknown WNV1 frame header value %i, please upload file for study\n", buf[2] >> 4);
  109. l->shift = 1;
  110. }
  111. }
  112. Y = p->data[0];
  113. U = p->data[1];
  114. V = p->data[2];
  115. for (j = 0; j < avctx->height; j++) {
  116. for (i = 0; i < avctx->width / 2; i++) {
  117. Y[i * 2] = wnv1_get_code(l, prev_y);
  118. prev_u = U[i] = wnv1_get_code(l, prev_u);
  119. prev_y = Y[(i * 2) + 1] = wnv1_get_code(l, Y[i * 2]);
  120. prev_v = V[i] = wnv1_get_code(l, prev_v);
  121. }
  122. Y += p->linesize[0];
  123. U += p->linesize[1];
  124. V += p->linesize[2];
  125. }
  126. *data_size = sizeof(AVFrame);
  127. *(AVFrame*)data = l->pic;
  128. return buf_size;
  129. }
  130. static int decode_init(AVCodecContext *avctx){
  131. WNV1Context * const l = avctx->priv_data;
  132. l->avctx = avctx;
  133. avctx->pix_fmt = PIX_FMT_YUV422P;
  134. return 0;
  135. }
  136. AVCodec wnv1_decoder = {
  137. "wnv1",
  138. CODEC_TYPE_VIDEO,
  139. CODEC_ID_WNV1,
  140. sizeof(WNV1Context),
  141. decode_init,
  142. NULL,
  143. NULL,
  144. decode_frame,
  145. CODEC_CAP_DR1,
  146. };