00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <stdio.h>
00023 #include <stdlib.h>
00024 #include <limits.h>
00025
00026 #include "libavutil/bswap.h"
00027 #include "libavutil/common.h"
00028 #include "libavutil/lzo.h"
00029 #include "libavutil/imgutils.h"
00030 #include "avcodec.h"
00031 #include "dsputil.h"
00032 #include "rtjpeg.h"
00033
00034 typedef struct {
00035 AVFrame pic;
00036 int codec_frameheader;
00037 int quality;
00038 int width, height;
00039 unsigned int decomp_size;
00040 unsigned char *decomp_buf;
00041 uint32_t lq[64], cq[64];
00042 RTJpegContext rtj;
00043 DSPContext dsp;
00044 } NuvContext;
00045
00046 static const uint8_t fallback_lquant[] = {
00047 16, 11, 10, 16, 24, 40, 51, 61,
00048 12, 12, 14, 19, 26, 58, 60, 55,
00049 14, 13, 16, 24, 40, 57, 69, 56,
00050 14, 17, 22, 29, 51, 87, 80, 62,
00051 18, 22, 37, 56, 68, 109, 103, 77,
00052 24, 35, 55, 64, 81, 104, 113, 92,
00053 49, 64, 78, 87, 103, 121, 120, 101,
00054 72, 92, 95, 98, 112, 100, 103, 99
00055 };
00056
00057 static const uint8_t fallback_cquant[] = {
00058 17, 18, 24, 47, 99, 99, 99, 99,
00059 18, 21, 26, 66, 99, 99, 99, 99,
00060 24, 26, 56, 99, 99, 99, 99, 99,
00061 47, 66, 99, 99, 99, 99, 99, 99,
00062 99, 99, 99, 99, 99, 99, 99, 99,
00063 99, 99, 99, 99, 99, 99, 99, 99,
00064 99, 99, 99, 99, 99, 99, 99, 99,
00065 99, 99, 99, 99, 99, 99, 99, 99
00066 };
00067
00075 static void copy_frame(AVFrame *f, const uint8_t *src, int width, int height)
00076 {
00077 AVPicture pic;
00078 avpicture_fill(&pic, src, PIX_FMT_YUV420P, width, height);
00079 av_picture_copy((AVPicture *)f, &pic, PIX_FMT_YUV420P, width, height);
00080 }
00081
00085 static int get_quant(AVCodecContext *avctx, NuvContext *c, const uint8_t *buf,
00086 int size)
00087 {
00088 int i;
00089 if (size < 2 * 64 * 4) {
00090 av_log(avctx, AV_LOG_ERROR, "insufficient rtjpeg quant data\n");
00091 return -1;
00092 }
00093 for (i = 0; i < 64; i++, buf += 4)
00094 c->lq[i] = AV_RL32(buf);
00095 for (i = 0; i < 64; i++, buf += 4)
00096 c->cq[i] = AV_RL32(buf);
00097 return 0;
00098 }
00099
00103 static void get_quant_quality(NuvContext *c, int quality)
00104 {
00105 int i;
00106 quality = FFMAX(quality, 1);
00107 for (i = 0; i < 64; i++) {
00108 c->lq[i] = (fallback_lquant[i] << 7) / quality;
00109 c->cq[i] = (fallback_cquant[i] << 7) / quality;
00110 }
00111 }
00112
00113 static int codec_reinit(AVCodecContext *avctx, int width, int height,
00114 int quality)
00115 {
00116 NuvContext *c = avctx->priv_data;
00117 width = FFALIGN(width, 2);
00118 height = FFALIGN(height, 2);
00119 if (quality >= 0)
00120 get_quant_quality(c, quality);
00121 if (width != c->width || height != c->height) {
00122
00123 int buf_size = 24 + height * width * 3 / 2 + AV_LZO_OUTPUT_PADDING;
00124 if (av_image_check_size(height, width, 0, avctx) < 0 ||
00125 buf_size > INT_MAX/8)
00126 return -1;
00127 avctx->width = c->width = width;
00128 avctx->height = c->height = height;
00129 av_fast_malloc(&c->decomp_buf, &c->decomp_size,
00130 buf_size);
00131 if (!c->decomp_buf) {
00132 av_log(avctx, AV_LOG_ERROR,
00133 "Can't allocate decompression buffer.\n");
00134 return AVERROR(ENOMEM);
00135 }
00136 ff_rtjpeg_decode_init(&c->rtj, &c->dsp, c->width, c->height,
00137 c->lq, c->cq);
00138 return 1;
00139 } else if (quality != c->quality)
00140 ff_rtjpeg_decode_init(&c->rtj, &c->dsp, c->width, c->height,
00141 c->lq, c->cq);
00142
00143 return 0;
00144 }
00145
00146 static int decode_frame(AVCodecContext *avctx, void *data, int *data_size,
00147 AVPacket *avpkt)
00148 {
00149 const uint8_t *buf = avpkt->data;
00150 int buf_size = avpkt->size;
00151 NuvContext *c = avctx->priv_data;
00152 AVFrame *picture = data;
00153 int orig_size = buf_size;
00154 int keyframe;
00155 int size_change = 0;
00156 int result;
00157 enum {
00158 NUV_UNCOMPRESSED = '0',
00159 NUV_RTJPEG = '1',
00160 NUV_RTJPEG_IN_LZO = '2',
00161 NUV_LZO = '3',
00162 NUV_BLACK = 'N',
00163 NUV_COPY_LAST = 'L'
00164 } comptype;
00165
00166 if (buf_size < 12) {
00167 av_log(avctx, AV_LOG_ERROR, "coded frame too small\n");
00168 return -1;
00169 }
00170
00171
00172 if (buf[0] == 'D' && buf[1] == 'R') {
00173 int ret;
00174
00175 buf = &buf[12];
00176 buf_size -= 12;
00177 ret = get_quant(avctx, c, buf, buf_size);
00178 if (ret < 0)
00179 return ret;
00180 ff_rtjpeg_decode_init(&c->rtj, &c->dsp, c->width, c->height, c->lq,
00181 c->cq);
00182 return orig_size;
00183 }
00184
00185 if (buf_size < 12 || buf[0] != 'V') {
00186 av_log(avctx, AV_LOG_ERROR, "not a nuv video frame\n");
00187 return -1;
00188 }
00189 comptype = buf[1];
00190 switch (comptype) {
00191 case NUV_RTJPEG_IN_LZO:
00192 case NUV_RTJPEG:
00193 keyframe = !buf[2];
00194 break;
00195 case NUV_COPY_LAST:
00196 keyframe = 0;
00197 break;
00198 default:
00199 keyframe = 1;
00200 break;
00201 }
00202 retry:
00203
00204 buf = &buf[12];
00205 buf_size -= 12;
00206 if (comptype == NUV_RTJPEG_IN_LZO || comptype == NUV_LZO) {
00207 int outlen = c->decomp_size - AV_LZO_OUTPUT_PADDING, inlen = buf_size;
00208 if (av_lzo1x_decode(c->decomp_buf, &outlen, buf, &inlen))
00209 av_log(avctx, AV_LOG_ERROR, "error during lzo decompression\n");
00210 buf = c->decomp_buf;
00211 buf_size = c->decomp_size - AV_LZO_OUTPUT_PADDING - outlen;
00212 }
00213 if (c->codec_frameheader) {
00214 int w, h, q;
00215 int res;
00216 if (buf_size < RTJPEG_HEADER_SIZE) {
00217 av_log(avctx, AV_LOG_ERROR, "Too small NUV video frame\n");
00218 return AVERROR_INVALIDDATA;
00219 }
00220
00221
00222
00223 if (buf[0] != 'V' && AV_RL16(&buf[4]) != 0x000c) {
00224 av_log(avctx, AV_LOG_ERROR, "Unknown secondary frame header (wrong codec_tag?)\n");
00225 return AVERROR_INVALIDDATA;
00226 }
00227 w = AV_RL16(&buf[6]);
00228 h = AV_RL16(&buf[8]);
00229 q = buf[10];
00230 res = codec_reinit(avctx, w, h, q);
00231 if (res < 0)
00232 return res;
00233 if (res) {
00234 buf = avpkt->data;
00235 buf_size = avpkt->size;
00236 size_change = 1;
00237 goto retry;
00238 }
00239 buf = &buf[RTJPEG_HEADER_SIZE];
00240 buf_size -= RTJPEG_HEADER_SIZE;
00241 }
00242
00243 if ((size_change || keyframe) && c->pic.data[0])
00244 avctx->release_buffer(avctx, &c->pic);
00245 c->pic.reference = 3;
00246 c->pic.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_READABLE |
00247 FF_BUFFER_HINTS_PRESERVE | FF_BUFFER_HINTS_REUSABLE;
00248 result = avctx->reget_buffer(avctx, &c->pic);
00249 if (result < 0) {
00250 av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
00251 return -1;
00252 }
00253
00254 c->pic.pict_type = keyframe ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_P;
00255 c->pic.key_frame = keyframe;
00256
00257 switch (comptype) {
00258 case NUV_LZO:
00259 case NUV_UNCOMPRESSED: {
00260 int height = c->height;
00261 if (buf_size < c->width * height * 3 / 2) {
00262 av_log(avctx, AV_LOG_ERROR, "uncompressed frame too short\n");
00263 height = buf_size / c->width / 3 * 2;
00264 }
00265 copy_frame(&c->pic, buf, c->width, height);
00266 break;
00267 }
00268 case NUV_RTJPEG_IN_LZO:
00269 case NUV_RTJPEG:
00270 ff_rtjpeg_decode_frame_yuv420(&c->rtj, &c->pic, buf, buf_size);
00271 break;
00272 case NUV_BLACK:
00273 memset(c->pic.data[0], 0, c->width * c->height);
00274 memset(c->pic.data[1], 128, c->width * c->height / 4);
00275 memset(c->pic.data[2], 128, c->width * c->height / 4);
00276 break;
00277 case NUV_COPY_LAST:
00278
00279 break;
00280 default:
00281 av_log(avctx, AV_LOG_ERROR, "unknown compression\n");
00282 return -1;
00283 }
00284
00285 *picture = c->pic;
00286 *data_size = sizeof(AVFrame);
00287 return orig_size;
00288 }
00289
00290 static av_cold int decode_init(AVCodecContext *avctx)
00291 {
00292 NuvContext *c = avctx->priv_data;
00293 avctx->pix_fmt = PIX_FMT_YUV420P;
00294 c->pic.data[0] = NULL;
00295 c->decomp_buf = NULL;
00296 c->quality = -1;
00297 c->width = 0;
00298 c->height = 0;
00299
00300 c->codec_frameheader = avctx->codec_tag == MKTAG('R', 'J', 'P', 'G');
00301
00302 if (avctx->extradata_size)
00303 get_quant(avctx, c, avctx->extradata, avctx->extradata_size);
00304
00305 ff_dsputil_init(&c->dsp, avctx);
00306
00307 if (codec_reinit(avctx, avctx->width, avctx->height, -1) < 0)
00308 return 1;
00309
00310 return 0;
00311 }
00312
00313 static av_cold int decode_end(AVCodecContext *avctx)
00314 {
00315 NuvContext *c = avctx->priv_data;
00316
00317 av_freep(&c->decomp_buf);
00318 if (c->pic.data[0])
00319 avctx->release_buffer(avctx, &c->pic);
00320
00321 return 0;
00322 }
00323
00324 AVCodec ff_nuv_decoder = {
00325 .name = "nuv",
00326 .type = AVMEDIA_TYPE_VIDEO,
00327 .id = AV_CODEC_ID_NUV,
00328 .priv_data_size = sizeof(NuvContext),
00329 .init = decode_init,
00330 .close = decode_end,
00331 .decode = decode_frame,
00332 .capabilities = CODEC_CAP_DR1,
00333 .long_name = NULL_IF_CONFIG_SMALL("NuppelVideo/RTJPEG"),
00334 };