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