3 * Copyright (c) 2006 Reimar Doeffinger
5 * This file is part of FFmpeg.
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.
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.
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
26 #include "libavutil/bswap.h"
27 #include "libavutil/common.h"
28 #include "libavutil/intreadwrite.h"
29 #include "libavutil/lzo.h"
30 #include "libavutil/imgutils.h"
38 int codec_frameheader
;
41 unsigned int decomp_size
;
42 unsigned char *decomp_buf
;
43 uint32_t lq
[64], cq
[64];
47 static const uint8_t fallback_lquant
[] = {
48 16, 11, 10, 16, 24, 40, 51, 61,
49 12, 12, 14, 19, 26, 58, 60, 55,
50 14, 13, 16, 24, 40, 57, 69, 56,
51 14, 17, 22, 29, 51, 87, 80, 62,
52 18, 22, 37, 56, 68, 109, 103, 77,
53 24, 35, 55, 64, 81, 104, 113, 92,
54 49, 64, 78, 87, 103, 121, 120, 101,
55 72, 92, 95, 98, 112, 100, 103, 99
58 static const uint8_t fallback_cquant
[] = {
59 17, 18, 24, 47, 99, 99, 99, 99,
60 18, 21, 26, 66, 99, 99, 99, 99,
61 24, 26, 56, 99, 99, 99, 99, 99,
62 47, 66, 99, 99, 99, 99, 99, 99,
63 99, 99, 99, 99, 99, 99, 99, 99,
64 99, 99, 99, 99, 99, 99, 99, 99,
65 99, 99, 99, 99, 99, 99, 99, 99,
66 99, 99, 99, 99, 99, 99, 99, 99
70 * @brief copy frame data from buffer to AVFrame, handling stride.
71 * @param f destination AVFrame
72 * @param src source buffer, does not use any line-stride
73 * @param width width of the video frame
74 * @param height height of the video frame
76 static void copy_frame(AVFrame
*f
, const uint8_t *src
, int width
, int height
)
79 avpicture_fill(&pic
, src
, AV_PIX_FMT_YUV420P
, width
, height
);
80 av_picture_copy((AVPicture
*)f
, &pic
, AV_PIX_FMT_YUV420P
, width
, height
);
84 * @brief extract quantization tables from codec data into our context
86 static int get_quant(AVCodecContext
*avctx
, NuvContext
*c
, const uint8_t *buf
,
90 if (size
< 2 * 64 * 4) {
91 av_log(avctx
, AV_LOG_ERROR
, "insufficient rtjpeg quant data\n");
92 return AVERROR_INVALIDDATA
;
94 for (i
= 0; i
< 64; i
++, buf
+= 4)
95 c
->lq
[i
] = AV_RL32(buf
);
96 for (i
= 0; i
< 64; i
++, buf
+= 4)
97 c
->cq
[i
] = AV_RL32(buf
);
102 * @brief set quantization tables from a quality value
104 static void get_quant_quality(NuvContext
*c
, int quality
)
107 quality
= FFMAX(quality
, 1);
108 for (i
= 0; i
< 64; i
++) {
109 c
->lq
[i
] = (fallback_lquant
[i
] << 7) / quality
;
110 c
->cq
[i
] = (fallback_cquant
[i
] << 7) / quality
;
114 static int codec_reinit(AVCodecContext
*avctx
, int width
, int height
,
117 NuvContext
*c
= avctx
->priv_data
;
120 width
= FFALIGN(width
, 2);
121 height
= FFALIGN(height
, 2);
123 get_quant_quality(c
, quality
);
124 if (width
!= c
->width
|| height
!= c
->height
) {
125 // also reserve space for a possible additional header
126 int buf_size
= height
* width
* 3 / 2
127 + FFMAX(AV_LZO_OUTPUT_PADDING
, FF_INPUT_BUFFER_PADDING_SIZE
)
128 + RTJPEG_HEADER_SIZE
;
129 if (buf_size
> INT_MAX
/8)
131 if ((ret
= av_image_check_size(height
, width
, 0, avctx
)) < 0)
133 avctx
->width
= c
->width
= width
;
134 avctx
->height
= c
->height
= height
;
135 av_fast_malloc(&c
->decomp_buf
, &c
->decomp_size
,
137 if (!c
->decomp_buf
) {
138 av_log(avctx
, AV_LOG_ERROR
,
139 "Can't allocate decompression buffer.\n");
140 return AVERROR(ENOMEM
);
142 ff_rtjpeg_decode_init(&c
->rtj
, c
->width
, c
->height
, c
->lq
, c
->cq
);
143 av_frame_unref(c
->pic
);
145 } else if (quality
!= c
->quality
)
146 ff_rtjpeg_decode_init(&c
->rtj
, c
->width
, c
->height
, c
->lq
, c
->cq
);
151 static int decode_frame(AVCodecContext
*avctx
, void *data
, int *got_frame
,
154 const uint8_t *buf
= avpkt
->data
;
155 int buf_size
= avpkt
->size
;
156 NuvContext
*c
= avctx
->priv_data
;
157 AVFrame
*picture
= data
;
158 int orig_size
= buf_size
;
161 int result
, init_frame
= !avctx
->frame_number
;
163 NUV_UNCOMPRESSED
= '0',
165 NUV_RTJPEG_IN_LZO
= '2',
172 av_log(avctx
, AV_LOG_ERROR
, "coded frame too small\n");
173 return AVERROR_INVALIDDATA
;
176 // codec data (rtjpeg quant tables)
177 if (buf
[0] == 'D' && buf
[1] == 'R') {
179 // skip rest of the frameheader.
182 ret
= get_quant(avctx
, c
, buf
, buf_size
);
185 ff_rtjpeg_decode_init(&c
->rtj
, c
->width
, c
->height
, c
->lq
, c
->cq
);
189 if (buf_size
< 12 || buf
[0] != 'V') {
190 av_log(avctx
, AV_LOG_ERROR
, "not a nuv video frame\n");
191 return AVERROR_INVALIDDATA
;
195 case NUV_RTJPEG_IN_LZO
:
207 // skip rest of the frameheader.
210 if (comptype
== NUV_RTJPEG_IN_LZO
|| comptype
== NUV_LZO
) {
211 int outlen
= c
->decomp_size
- FFMAX(FF_INPUT_BUFFER_PADDING_SIZE
, AV_LZO_OUTPUT_PADDING
);
212 int inlen
= buf_size
;
213 if (av_lzo1x_decode(c
->decomp_buf
, &outlen
, buf
, &inlen
)) {
214 av_log(avctx
, AV_LOG_ERROR
, "error during lzo decompression\n");
215 return AVERROR_INVALIDDATA
;
218 buf_size
= c
->decomp_size
- FFMAX(FF_INPUT_BUFFER_PADDING_SIZE
, AV_LZO_OUTPUT_PADDING
) - outlen
;
219 memset(c
->decomp_buf
+ buf_size
, 0, FF_INPUT_BUFFER_PADDING_SIZE
);
221 if (c
->codec_frameheader
) {
223 if (buf_size
< RTJPEG_HEADER_SIZE
) {
224 av_log(avctx
, AV_LOG_ERROR
, "Too small NUV video frame\n");
225 return AVERROR_INVALIDDATA
;
227 // There seem to exist two variants of this header: one starts with 'V'
228 // and 5 bytes unknown, the other matches current MythTV and is 4 bytes size,
229 // 1 byte header size (== 12), 1 byte version (== 0)
230 if (buf
[0] != 'V' && AV_RL16(&buf
[4]) != 0x000c) {
231 av_log(avctx
, AV_LOG_ERROR
, "Unknown secondary frame header (wrong codec_tag?)\n");
232 return AVERROR_INVALIDDATA
;
234 w
= AV_RL16(&buf
[6]);
235 h
= AV_RL16(&buf
[8]);
237 if ((result
= codec_reinit(avctx
, w
, h
, q
)) < 0)
241 buf_size
= avpkt
->size
;
245 buf
= &buf
[RTJPEG_HEADER_SIZE
];
246 buf_size
-= RTJPEG_HEADER_SIZE
;
249 if (size_change
|| keyframe
) {
250 av_frame_unref(c
->pic
);
254 if ((result
= ff_reget_buffer(avctx
, c
->pic
)) < 0)
257 memset(c
->pic
->data
[0], 0, avctx
->height
* c
->pic
->linesize
[0]);
258 memset(c
->pic
->data
[1], 0x80, avctx
->height
* c
->pic
->linesize
[1] / 2);
259 memset(c
->pic
->data
[2], 0x80, avctx
->height
* c
->pic
->linesize
[2] / 2);
262 c
->pic
->pict_type
= keyframe
? AV_PICTURE_TYPE_I
: AV_PICTURE_TYPE_P
;
263 c
->pic
->key_frame
= keyframe
;
264 // decompress/copy/whatever data
267 case NUV_UNCOMPRESSED
: {
268 int height
= c
->height
;
269 if (buf_size
< c
->width
* height
* 3 / 2) {
270 av_log(avctx
, AV_LOG_ERROR
, "uncompressed frame too short\n");
271 height
= buf_size
/ c
->width
/ 3 * 2;
274 copy_frame(c
->pic
, buf
, c
->width
, height
);
277 case NUV_RTJPEG_IN_LZO
:
279 ret
= ff_rtjpeg_decode_frame_yuv420(&c
->rtj
, c
->pic
, buf
, buf_size
);
284 memset(c
->pic
->data
[0], 0, c
->width
* c
->height
);
285 memset(c
->pic
->data
[1], 128, c
->width
* c
->height
/ 4);
286 memset(c
->pic
->data
[2], 128, c
->width
* c
->height
/ 4);
289 /* nothing more to do here */
292 av_log(avctx
, AV_LOG_ERROR
, "unknown compression\n");
293 return AVERROR_INVALIDDATA
;
296 if ((result
= av_frame_ref(picture
, c
->pic
)) < 0)
303 static av_cold
int decode_init(AVCodecContext
*avctx
)
305 NuvContext
*c
= avctx
->priv_data
;
308 c
->pic
= av_frame_alloc();
310 return AVERROR(ENOMEM
);
312 avctx
->pix_fmt
= AV_PIX_FMT_YUV420P
;
313 c
->decomp_buf
= NULL
;
318 c
->codec_frameheader
= avctx
->codec_tag
== MKTAG('R', 'J', 'P', 'G');
320 if (avctx
->extradata_size
)
321 get_quant(avctx
, c
, avctx
->extradata
, avctx
->extradata_size
);
323 ff_rtjpeg_init(&c
->rtj
, avctx
);
325 if ((ret
= codec_reinit(avctx
, avctx
->width
, avctx
->height
, -1)) < 0)
331 static av_cold
int decode_end(AVCodecContext
*avctx
)
333 NuvContext
*c
= avctx
->priv_data
;
335 av_freep(&c
->decomp_buf
);
336 av_frame_free(&c
->pic
);
341 AVCodec ff_nuv_decoder
= {
343 .long_name
= NULL_IF_CONFIG_SMALL("NuppelVideo/RTJPEG"),
344 .type
= AVMEDIA_TYPE_VIDEO
,
345 .id
= AV_CODEC_ID_NUV
,
346 .priv_data_size
= sizeof(NuvContext
),
349 .decode
= decode_frame
,
350 .capabilities
= CODEC_CAP_DR1
,