Libav 0.7.1
|
00001 /* 00002 * NuppelVideo decoder 00003 * Copyright (c) 2006 Reimar Doeffinger 00004 * 00005 * This file is part of Libav. 00006 * 00007 * Libav is free software; you can redistribute it and/or 00008 * modify it under the terms of the GNU Lesser General Public 00009 * License as published by the Free Software Foundation; either 00010 * version 2.1 of the License, or (at your option) any later version. 00011 * 00012 * Libav is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00015 * Lesser General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU Lesser General Public 00018 * License along with Libav; if not, write to the Free Software 00019 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00020 */ 00021 #include <stdio.h> 00022 #include <stdlib.h> 00023 00024 #include "libavutil/bswap.h" 00025 #include "libavutil/lzo.h" 00026 #include "libavutil/imgutils.h" 00027 #include "avcodec.h" 00028 #include "dsputil.h" 00029 #include "rtjpeg.h" 00030 00031 typedef struct { 00032 AVFrame pic; 00033 int codec_frameheader; 00034 int quality; 00035 int width, height; 00036 unsigned int decomp_size; 00037 unsigned char* decomp_buf; 00038 uint32_t lq[64], cq[64]; 00039 RTJpegContext rtj; 00040 DSPContext dsp; 00041 } NuvContext; 00042 00043 static const uint8_t fallback_lquant[] = { 00044 16, 11, 10, 16, 24, 40, 51, 61, 00045 12, 12, 14, 19, 26, 58, 60, 55, 00046 14, 13, 16, 24, 40, 57, 69, 56, 00047 14, 17, 22, 29, 51, 87, 80, 62, 00048 18, 22, 37, 56, 68, 109, 103, 77, 00049 24, 35, 55, 64, 81, 104, 113, 92, 00050 49, 64, 78, 87, 103, 121, 120, 101, 00051 72, 92, 95, 98, 112, 100, 103, 99 00052 }; 00053 00054 static const uint8_t fallback_cquant[] = { 00055 17, 18, 24, 47, 99, 99, 99, 99, 00056 18, 21, 26, 66, 99, 99, 99, 99, 00057 24, 26, 56, 99, 99, 99, 99, 99, 00058 47, 66, 99, 99, 99, 99, 99, 99, 00059 99, 99, 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 }; 00064 00072 static void copy_frame(AVFrame *f, const uint8_t *src, 00073 int width, int height) { 00074 AVPicture pic; 00075 avpicture_fill(&pic, src, PIX_FMT_YUV420P, width, height); 00076 av_picture_copy((AVPicture *)f, &pic, PIX_FMT_YUV420P, width, height); 00077 } 00078 00082 static int get_quant(AVCodecContext *avctx, NuvContext *c, 00083 const uint8_t *buf, int size) { 00084 int i; 00085 if (size < 2 * 64 * 4) { 00086 av_log(avctx, AV_LOG_ERROR, "insufficient rtjpeg quant data\n"); 00087 return -1; 00088 } 00089 for (i = 0; i < 64; i++, buf += 4) 00090 c->lq[i] = AV_RL32(buf); 00091 for (i = 0; i < 64; i++, buf += 4) 00092 c->cq[i] = AV_RL32(buf); 00093 return 0; 00094 } 00095 00099 static void get_quant_quality(NuvContext *c, int quality) { 00100 int i; 00101 quality = FFMAX(quality, 1); 00102 for (i = 0; i < 64; i++) { 00103 c->lq[i] = (fallback_lquant[i] << 7) / quality; 00104 c->cq[i] = (fallback_cquant[i] << 7) / quality; 00105 } 00106 } 00107 00108 static int codec_reinit(AVCodecContext *avctx, int width, int height, int quality) { 00109 NuvContext *c = avctx->priv_data; 00110 width = (width + 1) & ~1; 00111 height = (height + 1) & ~1; 00112 if (quality >= 0) 00113 get_quant_quality(c, quality); 00114 if (width != c->width || height != c->height) { 00115 if (av_image_check_size(height, width, 0, avctx) < 0) 00116 return 0; 00117 avctx->width = c->width = width; 00118 avctx->height = c->height = height; 00119 av_fast_malloc(&c->decomp_buf, &c->decomp_size, c->height * c->width * 3 / 2); 00120 if (!c->decomp_buf) { 00121 av_log(avctx, AV_LOG_ERROR, "Can't allocate decompression buffer.\n"); 00122 return 0; 00123 } 00124 rtjpeg_decode_init(&c->rtj, &c->dsp, c->width, c->height, c->lq, c->cq); 00125 } else if (quality != c->quality) 00126 rtjpeg_decode_init(&c->rtj, &c->dsp, c->width, c->height, c->lq, c->cq); 00127 return 1; 00128 } 00129 00130 static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, 00131 AVPacket *avpkt) { 00132 const uint8_t *buf = avpkt->data; 00133 int buf_size = avpkt->size; 00134 NuvContext *c = avctx->priv_data; 00135 AVFrame *picture = data; 00136 int orig_size = buf_size; 00137 int keyframe; 00138 int result; 00139 enum {NUV_UNCOMPRESSED = '0', NUV_RTJPEG = '1', 00140 NUV_RTJPEG_IN_LZO = '2', NUV_LZO = '3', 00141 NUV_BLACK = 'N', NUV_COPY_LAST = 'L'} comptype; 00142 00143 if (buf_size < 12) { 00144 av_log(avctx, AV_LOG_ERROR, "coded frame too small\n"); 00145 return -1; 00146 } 00147 00148 // codec data (rtjpeg quant tables) 00149 if (buf[0] == 'D' && buf[1] == 'R') { 00150 int ret; 00151 // skip rest of the frameheader. 00152 buf = &buf[12]; 00153 buf_size -= 12; 00154 ret = get_quant(avctx, c, buf, buf_size); 00155 if (ret < 0) 00156 return ret; 00157 rtjpeg_decode_init(&c->rtj, &c->dsp, c->width, c->height, c->lq, c->cq); 00158 return orig_size; 00159 } 00160 00161 if (buf[0] != 'V' || buf_size < 12) { 00162 av_log(avctx, AV_LOG_ERROR, "not a nuv video frame\n"); 00163 return -1; 00164 } 00165 comptype = buf[1]; 00166 switch (comptype) { 00167 case NUV_RTJPEG_IN_LZO: 00168 case NUV_RTJPEG: 00169 keyframe = !buf[2]; break; 00170 case NUV_COPY_LAST: 00171 keyframe = 0; break; 00172 default: 00173 keyframe = 1; break; 00174 } 00175 // skip rest of the frameheader. 00176 buf = &buf[12]; 00177 buf_size -= 12; 00178 if (comptype == NUV_RTJPEG_IN_LZO || comptype == NUV_LZO) { 00179 int outlen = c->decomp_size, inlen = buf_size; 00180 if (av_lzo1x_decode(c->decomp_buf, &outlen, buf, &inlen)) 00181 av_log(avctx, AV_LOG_ERROR, "error during lzo decompression\n"); 00182 buf = c->decomp_buf; 00183 buf_size = c->decomp_size; 00184 } 00185 if (c->codec_frameheader) { 00186 int w, h, q; 00187 if (buf_size < 12) { 00188 av_log(avctx, AV_LOG_ERROR, "invalid nuv video frame\n"); 00189 return -1; 00190 } 00191 w = AV_RL16(&buf[6]); 00192 h = AV_RL16(&buf[8]); 00193 q = buf[10]; 00194 if (!codec_reinit(avctx, w, h, q)) 00195 return -1; 00196 buf = &buf[12]; 00197 buf_size -= 12; 00198 } 00199 00200 if (keyframe && c->pic.data[0]) 00201 avctx->release_buffer(avctx, &c->pic); 00202 c->pic.reference = 3; 00203 c->pic.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_READABLE | 00204 FF_BUFFER_HINTS_PRESERVE | FF_BUFFER_HINTS_REUSABLE; 00205 result = avctx->reget_buffer(avctx, &c->pic); 00206 if (result < 0) { 00207 av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); 00208 return -1; 00209 } 00210 00211 c->pic.pict_type = keyframe ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_P; 00212 c->pic.key_frame = keyframe; 00213 // decompress/copy/whatever data 00214 switch (comptype) { 00215 case NUV_LZO: 00216 case NUV_UNCOMPRESSED: { 00217 int height = c->height; 00218 if (buf_size < c->width * height * 3 / 2) { 00219 av_log(avctx, AV_LOG_ERROR, "uncompressed frame too short\n"); 00220 height = buf_size / c->width / 3 * 2; 00221 } 00222 copy_frame(&c->pic, buf, c->width, height); 00223 break; 00224 } 00225 case NUV_RTJPEG_IN_LZO: 00226 case NUV_RTJPEG: { 00227 rtjpeg_decode_frame_yuv420(&c->rtj, &c->pic, buf, buf_size); 00228 break; 00229 } 00230 case NUV_BLACK: { 00231 memset(c->pic.data[0], 0, c->width * c->height); 00232 memset(c->pic.data[1], 128, c->width * c->height / 4); 00233 memset(c->pic.data[2], 128, c->width * c->height / 4); 00234 break; 00235 } 00236 case NUV_COPY_LAST: { 00237 /* nothing more to do here */ 00238 break; 00239 } 00240 default: 00241 av_log(avctx, AV_LOG_ERROR, "unknown compression\n"); 00242 return -1; 00243 } 00244 00245 *picture = c->pic; 00246 *data_size = sizeof(AVFrame); 00247 return orig_size; 00248 } 00249 00250 static av_cold int decode_init(AVCodecContext *avctx) { 00251 NuvContext *c = avctx->priv_data; 00252 avctx->pix_fmt = PIX_FMT_YUV420P; 00253 c->pic.data[0] = NULL; 00254 c->decomp_buf = NULL; 00255 c->quality = -1; 00256 c->width = 0; 00257 c->height = 0; 00258 c->codec_frameheader = avctx->codec_tag == MKTAG('R', 'J', 'P', 'G'); 00259 if (avctx->extradata_size) 00260 get_quant(avctx, c, avctx->extradata, avctx->extradata_size); 00261 dsputil_init(&c->dsp, avctx); 00262 if (!codec_reinit(avctx, avctx->width, avctx->height, -1)) 00263 return 1; 00264 return 0; 00265 } 00266 00267 static av_cold int decode_end(AVCodecContext *avctx) { 00268 NuvContext *c = avctx->priv_data; 00269 av_freep(&c->decomp_buf); 00270 if (c->pic.data[0]) 00271 avctx->release_buffer(avctx, &c->pic); 00272 return 0; 00273 } 00274 00275 AVCodec ff_nuv_decoder = { 00276 "nuv", 00277 AVMEDIA_TYPE_VIDEO, 00278 CODEC_ID_NUV, 00279 sizeof(NuvContext), 00280 decode_init, 00281 NULL, 00282 decode_end, 00283 decode_frame, 00284 CODEC_CAP_DR1, 00285 .long_name = NULL_IF_CONFIG_SMALL("NuppelVideo/RTJPEG"), 00286 }; 00287