]> git.sesse.net Git - ffmpeg/blob - libavcodec/rtjpeg.c
libopenh264dec: Export the decoded profile and level in AVCodecContext
[ffmpeg] / libavcodec / rtjpeg.c
1 /*
2  * RTJpeg decoding functions
3  * Copyright (c) 2006 Reimar Doeffinger
4  *
5  * This file is part of Libav.
6  *
7  * Libav 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  * Libav 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 Libav; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21
22 #include "libavutil/common.h"
23
24 #include "bitstream.h"
25 #include "rtjpeg.h"
26
27 #define PUT_COEFF(c) \
28     i = scan[coeff--]; \
29     block[i] = (c) * quant[i];
30
31 /// aligns the bitstream to the given power of two
32 #define ALIGN(a) \
33     n = (-bitstream_tell(bc)) & (a - 1); \
34     if (n)                               \
35         bitstream_skip(bc, n);
36
37 /**
38  * @brief read one block from stream
39  * @param bc contains stream data
40  * @param block where data is written to
41  * @param scan array containing the mapping stream address -> block position
42  * @param quant quantization factors
43  * @return 0 means the block is not coded, < 0 means an error occurred.
44  *
45  * Note: BitstreamContext is used to make the code simpler, since all data is
46  * aligned this could be done faster in a different way, e.g. as it is done
47  * in MPlayer libmpcodecs/native/rtjpegn.c.
48  */
49 static inline int get_block(BitstreamContext *bc, int16_t *block,
50                             const uint8_t *scan, const uint32_t *quant)
51 {
52     int coeff, i, n;
53     int8_t ac;
54     uint8_t dc = bitstream_read(bc, 8);
55
56     // block not coded
57     if (dc == 255)
58        return 0;
59
60     // number of non-zero coefficients
61     coeff = bitstream_read(bc, 6);
62     if (bitstream_bits_left(bc) < (coeff << 1))
63         return AVERROR_INVALIDDATA;
64
65     // normally we would only need to clear the (63 - coeff) last values,
66     // but since we do not know where they are we just clear the whole block
67     memset(block, 0, 64 * sizeof(int16_t));
68
69     // 2 bits per coefficient
70     while (coeff) {
71         ac = bitstream_read_signed(bc, 2);
72         if (ac == -2)
73             break; // continue with more bits
74         PUT_COEFF(ac);
75     }
76
77     // 4 bits per coefficient
78     ALIGN(4);
79     if (bitstream_bits_left(bc) < (coeff << 2))
80         return AVERROR_INVALIDDATA;
81     while (coeff) {
82         ac = bitstream_read_signed(bc, 4);
83         if (ac == -8)
84             break; // continue with more bits
85         PUT_COEFF(ac);
86     }
87
88     // 8 bits per coefficient
89     ALIGN(8);
90     if (bitstream_bits_left(bc) < (coeff << 3))
91         return AVERROR_INVALIDDATA;
92     while (coeff) {
93         ac = bitstream_read_signed(bc, 8);
94         PUT_COEFF(ac);
95     }
96
97     PUT_COEFF(dc);
98     return 1;
99 }
100
101 /**
102  * @brief decode one rtjpeg YUV420 frame
103  * @param c context, must be initialized via ff_rtjpeg_decode_init
104  * @param f AVFrame to place decoded frame into. If parts of the frame
105  *          are not coded they are left unchanged, so consider initializing it
106  * @param buf buffer containing input data
107  * @param buf_size length of input data in bytes
108  * @return number of bytes consumed from the input buffer
109  */
110 int ff_rtjpeg_decode_frame_yuv420(RTJpegContext *c, AVFrame *f,
111                                   const uint8_t *buf, int buf_size) {
112     BitstreamContext bc;
113     int w = c->w / 16, h = c->h / 16;
114     int x, y, ret;
115     uint8_t *y1 = f->data[0], *y2 = f->data[0] + 8 * f->linesize[0];
116     uint8_t *u = f->data[1], *v = f->data[2];
117
118     if ((ret = bitstream_init8(&bc, buf, buf_size)) < 0)
119         return ret;
120
121     for (y = 0; y < h; y++) {
122         for (x = 0; x < w; x++) {
123 #define BLOCK(quant, dst, stride) do { \
124     int res = get_block(&bc, block, c->scan, quant); \
125     if (res < 0) \
126         return res; \
127     if (res > 0) \
128         c->idsp.idct_put(dst, stride, block); \
129 } while (0)
130             int16_t *block = c->block;
131             BLOCK(c->lquant, y1, f->linesize[0]);
132             y1 += 8;
133             BLOCK(c->lquant, y1, f->linesize[0]);
134             y1 += 8;
135             BLOCK(c->lquant, y2, f->linesize[0]);
136             y2 += 8;
137             BLOCK(c->lquant, y2, f->linesize[0]);
138             y2 += 8;
139             BLOCK(c->cquant, u,  f->linesize[1]);
140             u += 8;
141             BLOCK(c->cquant, v,  f->linesize[2]);
142             v += 8;
143         }
144         y1 += 2 * 8 * (f->linesize[0] - w);
145         y2 += 2 * 8 * (f->linesize[0] - w);
146         u += 8 * (f->linesize[1] - w);
147         v += 8 * (f->linesize[2] - w);
148     }
149     return bitstream_tell(&bc) / 8;
150 }
151
152 /**
153  * @brief initialize an RTJpegContext, may be called multiple times
154  * @param c context to initialize
155  * @param width width of image, will be rounded down to the nearest multiple
156  *              of 16 for decoding
157  * @param height height of image, will be rounded down to the nearest multiple
158  *              of 16 for decoding
159  * @param lquant luma quantization table to use
160  * @param cquant chroma quantization table to use
161  */
162 void ff_rtjpeg_decode_init(RTJpegContext *c, int width, int height,
163                            const uint32_t *lquant, const uint32_t *cquant) {
164     int i;
165     for (i = 0; i < 64; i++) {
166         int p = c->idsp.idct_permutation[i];
167         c->lquant[p] = lquant[i];
168         c->cquant[p] = cquant[i];
169     }
170     c->w = width;
171     c->h = height;
172 }
173
174 void ff_rtjpeg_init(RTJpegContext *c, AVCodecContext *avctx)
175 {
176     int i;
177
178     ff_idctdsp_init(&c->idsp, avctx);
179
180     for (i = 0; i < 64; i++) {
181         int z = ff_zigzag_direct[i];
182         z = ((z << 3) | (z >> 3)) & 63; // rtjpeg uses a transposed variant
183
184         // permute the scan and quantization tables for the chosen idct
185         c->scan[i] = c->idsp.idct_permutation[z];
186     }
187 }