Change license headers to say 'FFmpeg' instead of 'this program/this library'
[ffmpeg.git] / libavcodec / wnv1.c
1 /*
2  * Winnov WNV1 codec
3  * Copyright (c) 2005 Konstantin Shishkov
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
23 /**
24  * @file wnv1.c
25  * Winnov WNV1 codec.
26  */
27
28 #include "avcodec.h"
29 #include "common.h"
30 #include "bitstream.h"
31
32
33 typedef struct WNV1Context{
34     AVCodecContext *avctx;
35     AVFrame pic;
36
37     int shift;
38     GetBitContext gb;
39 } WNV1Context;
40
41 static uint16_t code_tab[16][2]={
42 {0x1FD,9}, {0xFD,8}, {0x7D,7}, {0x3D,6}, {0x1D,5}, {0x0D,4}, {0x005,3},
43 {0x000,1},
44 {0x004,3}, {0x0C,4}, {0x1C,5}, {0x3C,6}, {0x7C,7}, {0xFC,8}, {0x1FC,9}, {0xFF,8}
45 };
46
47 #define CODE_VLC_BITS 9
48 static VLC code_vlc;
49
50 /* returns modified base_value */
51 static inline int wnv1_get_code(WNV1Context *w, int base_value)
52 {
53     int v = get_vlc2(&w->gb, code_vlc.table, CODE_VLC_BITS, 1);
54
55     if(v==15)
56         return ff_reverse[ get_bits(&w->gb, 8 - w->shift) ];
57     else
58         return base_value + ((v - 7)<<w->shift);
59 }
60
61 static int decode_frame(AVCodecContext *avctx,
62                         void *data, int *data_size,
63                         uint8_t *buf, int buf_size)
64 {
65     WNV1Context * const l = avctx->priv_data;
66     AVFrame * const p= (AVFrame*)&l->pic;
67     unsigned char *Y,*U,*V;
68     int i, j;
69     int prev_y = 0, prev_u = 0, prev_v = 0;
70
71     if(p->data[0])
72         avctx->release_buffer(avctx, p);
73
74     p->reference = 0;
75     if(avctx->get_buffer(avctx, p) < 0){
76         av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
77         return -1;
78     }
79     p->key_frame = 1;
80
81     for(i=8; i<buf_size; i++)
82         buf[i]= ff_reverse[ buf[i] ]; //FIXME ensure that the buffer is modifyable or use a temp one
83     init_get_bits(&l->gb, buf+8, (buf_size-8)*8);
84
85     if (buf[2] >> 4 == 6)
86         l->shift = 2;
87     else {
88         l->shift = 8 - (buf[2] >> 4);
89         if (l->shift > 4) {
90             av_log(avctx, AV_LOG_ERROR, "Unknown WNV1 frame header value %i, please upload file for study\n", buf[2] >> 4);
91             l->shift = 4;
92         }
93         if (l->shift < 1) {
94             av_log(avctx, AV_LOG_ERROR, "Unknown WNV1 frame header value %i, please upload file for study\n", buf[2] >> 4);
95             l->shift = 1;
96         }
97     }
98
99     Y = p->data[0];
100     U = p->data[1];
101     V = p->data[2];
102     for (j = 0; j < avctx->height; j++) {
103         for (i = 0; i < avctx->width / 2; i++) {
104             Y[i * 2] = wnv1_get_code(l, prev_y);
105             prev_u = U[i] = wnv1_get_code(l, prev_u);
106             prev_y = Y[(i * 2) + 1] = wnv1_get_code(l, Y[i * 2]);
107             prev_v = V[i] = wnv1_get_code(l, prev_v);
108         }
109         Y += p->linesize[0];
110         U += p->linesize[1];
111         V += p->linesize[2];
112     }
113
114
115     *data_size = sizeof(AVFrame);
116     *(AVFrame*)data = l->pic;
117
118     return buf_size;
119 }
120
121 static int decode_init(AVCodecContext *avctx){
122     WNV1Context * const l = avctx->priv_data;
123
124     l->avctx = avctx;
125     avctx->pix_fmt = PIX_FMT_YUV422P;
126
127     if(!code_vlc.table){
128         init_vlc(&code_vlc, CODE_VLC_BITS, 16,
129                     &code_tab[0][1], 4, 2,
130                     &code_tab[0][0], 4, 2, 1);
131     }
132
133     return 0;
134 }
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 };