1/*
2 * ATI VCR1 codec
3 * Copyright (c) 2003 Michael Niedermayer
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 * @file
24 * ati vcr1 codec.
25 */
26
27#include "avcodec.h"
28#include "dsputil.h"
29
30//#undef NDEBUG
31//#include <assert.h>
32
33/* Disable the encoder. */
34#undef CONFIG_VCR1_ENCODER
35#define CONFIG_VCR1_ENCODER 0
36
37typedef struct VCR1Context{
38    AVCodecContext *avctx;
39    AVFrame picture;
40    int delta[16];
41    int offset[4];
42} VCR1Context;
43
44static int decode_frame(AVCodecContext *avctx,
45                        void *data, int *data_size,
46                        AVPacket *avpkt)
47{
48    const uint8_t *buf = avpkt->data;
49    int buf_size = avpkt->size;
50    VCR1Context * const a = avctx->priv_data;
51    AVFrame *picture = data;
52    AVFrame * const p= (AVFrame*)&a->picture;
53    const uint8_t *bytestream= buf;
54    int i, x, y;
55
56    if(p->data[0])
57        avctx->release_buffer(avctx, p);
58
59    p->reference= 0;
60    if(avctx->get_buffer(avctx, p) < 0){
61        av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
62        return -1;
63    }
64    p->pict_type= FF_I_TYPE;
65    p->key_frame= 1;
66
67    for(i=0; i<16; i++){
68        a->delta[i]= *(bytestream++);
69        bytestream++;
70    }
71
72    for(y=0; y<avctx->height; y++){
73        int offset;
74        uint8_t *luma= &a->picture.data[0][ y*a->picture.linesize[0] ];
75
76        if((y&3) == 0){
77            uint8_t *cb= &a->picture.data[1][ (y>>2)*a->picture.linesize[1] ];
78            uint8_t *cr= &a->picture.data[2][ (y>>2)*a->picture.linesize[2] ];
79
80            for(i=0; i<4; i++)
81                a->offset[i]= *(bytestream++);
82
83            offset= a->offset[0] - a->delta[ bytestream[2]&0xF ];
84            for(x=0; x<avctx->width; x+=4){
85                luma[0]=( offset += a->delta[ bytestream[2]&0xF ]);
86                luma[1]=( offset += a->delta[ bytestream[2]>>4  ]);
87                luma[2]=( offset += a->delta[ bytestream[0]&0xF ]);
88                luma[3]=( offset += a->delta[ bytestream[0]>>4  ]);
89                luma += 4;
90
91                *(cb++) = bytestream[3];
92                *(cr++) = bytestream[1];
93
94                bytestream+= 4;
95            }
96        }else{
97            offset= a->offset[y&3] - a->delta[ bytestream[2]&0xF ];
98
99            for(x=0; x<avctx->width; x+=8){
100                luma[0]=( offset += a->delta[ bytestream[2]&0xF ]);
101                luma[1]=( offset += a->delta[ bytestream[2]>>4  ]);
102                luma[2]=( offset += a->delta[ bytestream[3]&0xF ]);
103                luma[3]=( offset += a->delta[ bytestream[3]>>4  ]);
104                luma[4]=( offset += a->delta[ bytestream[0]&0xF ]);
105                luma[5]=( offset += a->delta[ bytestream[0]>>4  ]);
106                luma[6]=( offset += a->delta[ bytestream[1]&0xF ]);
107                luma[7]=( offset += a->delta[ bytestream[1]>>4  ]);
108                luma += 8;
109                bytestream+= 4;
110            }
111        }
112    }
113
114    *picture= *(AVFrame*)&a->picture;
115    *data_size = sizeof(AVPicture);
116
117    emms_c();
118
119    return buf_size;
120}
121
122#if CONFIG_VCR1_ENCODER
123static int encode_frame(AVCodecContext *avctx, unsigned char *buf, int buf_size, void *data){
124    VCR1Context * const a = avctx->priv_data;
125    AVFrame *pict = data;
126    AVFrame * const p= (AVFrame*)&a->picture;
127    int size;
128
129    *p = *pict;
130    p->pict_type= FF_I_TYPE;
131    p->key_frame= 1;
132
133    emms_c();
134
135    align_put_bits(&a->pb);
136    while(get_bit_count(&a->pb)&31)
137        put_bits(&a->pb, 8, 0);
138
139    size= get_bit_count(&a->pb)/32;
140
141    return size*4;
142}
143#endif
144
145static av_cold void common_init(AVCodecContext *avctx){
146    VCR1Context * const a = avctx->priv_data;
147
148    avctx->coded_frame= (AVFrame*)&a->picture;
149    a->avctx= avctx;
150}
151
152static av_cold int decode_init(AVCodecContext *avctx){
153
154    common_init(avctx);
155
156    avctx->pix_fmt= PIX_FMT_YUV410P;
157
158    return 0;
159}
160
161static av_cold int decode_end(AVCodecContext *avctx){
162    VCR1Context *s = avctx->priv_data;
163
164    if (s->picture.data[0])
165        avctx->release_buffer(avctx, &s->picture);
166
167    return 0;
168}
169
170#if CONFIG_VCR1_ENCODER
171static av_cold int encode_init(AVCodecContext *avctx){
172
173    common_init(avctx);
174
175    return 0;
176}
177#endif
178
179AVCodec vcr1_decoder = {
180    "vcr1",
181    AVMEDIA_TYPE_VIDEO,
182    CODEC_ID_VCR1,
183    sizeof(VCR1Context),
184    decode_init,
185    NULL,
186    decode_end,
187    decode_frame,
188    CODEC_CAP_DR1,
189    .long_name = NULL_IF_CONFIG_SMALL("ATI VCR1"),
190};
191
192#if CONFIG_VCR1_ENCODER
193AVCodec vcr1_encoder = {
194    "vcr1",
195    AVMEDIA_TYPE_VIDEO,
196    CODEC_ID_VCR1,
197    sizeof(VCR1Context),
198    encode_init,
199    encode_frame,
200    //encode_end,
201    .long_name = NULL_IF_CONFIG_SMALL("ATI VCR1"),
202};
203#endif
204