Originally committed as revision 5232 to svn://svn.ffmpeg.org/ffmpeg/trunk
| ... | ... |
@@ -134,6 +134,7 @@ Codecs: |
| 134 | 134 |
msmpeg4.c, msmpeg4data.h Michael Niedermayer |
| 135 | 135 |
msrle.c Mike Melanson |
| 136 | 136 |
msvideo1.c Mike Melanson |
| 137 |
+ nuv.c Reimar Doeffinger |
|
| 137 | 138 |
oggtheora.c Mans Rullgard |
| 138 | 139 |
qdm2.c, qdm2data.h Roberto Togni |
| 139 | 140 |
qdrw.c Kostya Shishkov |
| ... | ... |
@@ -142,6 +143,7 @@ Codecs: |
| 142 | 142 |
ra144.c, ra144.h, ra288.c, ra288.h Roberto Togni |
| 143 | 143 |
resample2.c Michael Niedermayer |
| 144 | 144 |
rpza.c Roberto Togni |
| 145 |
+ rtjpeg.c, rtjpeg.h Reimar Doeffinger |
|
| 145 | 146 |
rv10.c Michael Niedermayer |
| 146 | 147 |
smc.c Mike Melanson |
| 147 | 148 |
snow.c Michael Niedermayer, Loren Merritt |
| ... | ... |
@@ -191,6 +193,7 @@ Muxers/Demuxers: |
| 191 | 191 |
mpegts* Mans Rullgard |
| 192 | 192 |
nsvdec.c Francois Revol |
| 193 | 193 |
nut.c Alex Beregszaszi |
| 194 |
+ nuv.c Reimar Doeffinger |
|
| 194 | 195 |
ogg2.c, ogg2.h Mans Rullgard |
| 195 | 196 |
oggparsevorbis.c Mans Rullgard |
| 196 | 197 |
psxstr.c Mike Melanson |
| ... | ... |
@@ -799,6 +799,7 @@ following image formats are supported: |
| 799 | 799 |
@item ZMBV @tab @tab X @tab |
| 800 | 800 |
@item AVS Video @tab @tab X @tab Video encoding used by the Creature Shock game. |
| 801 | 801 |
@item Smacker Video @tab @tab X @tab Video encoding used in Smacker. |
| 802 |
+@item RTjpeg @tab @tab X @tab Video encoding used in NuppelVideo files. |
|
| 802 | 803 |
@end multitable |
| 803 | 804 |
|
| 804 | 805 |
@code{X} means that encoding (resp. decoding) is supported.
|
| ... | ... |
@@ -180,6 +180,11 @@ ifeq ($(CONFIG_CSCD_DECODER),yes) |
| 180 | 180 |
OBJS+= cscd.o |
| 181 | 181 |
OBJS+= lzo.o |
| 182 | 182 |
endif |
| 183 |
+ifeq ($(CONFIG_NUV_DECODER),yes) |
|
| 184 |
+ OBJS+= nuv.o |
|
| 185 |
+ OBJS+= rtjpeg.o |
|
| 186 |
+ OBJS+= lzo.o |
|
| 187 |
+endif |
|
| 183 | 188 |
ifeq ($(CONFIG_ULTI_DECODER),yes) |
| 184 | 189 |
OBJS+= ulti.o |
| 185 | 190 |
endif |
| ... | ... |
@@ -267,6 +267,9 @@ void avcodec_register_all(void) |
| 267 | 267 |
#ifdef CONFIG_CSCD_DECODER |
| 268 | 268 |
register_avcodec(&cscd_decoder); |
| 269 | 269 |
#endif //CONFIG_CSCD_DECODER |
| 270 |
+#ifdef CONFIG_NUV_DECODER |
|
| 271 |
+ register_avcodec(&nuv_decoder); |
|
| 272 |
+#endif //CONFIG_NUV_DECODER |
|
| 270 | 273 |
#ifdef CONFIG_ULTI_DECODER |
| 271 | 274 |
register_avcodec(&ulti_decoder); |
| 272 | 275 |
#endif //CONFIG_ULTI_DECODER |
| ... | ... |
@@ -119,6 +119,7 @@ enum CodecID {
|
| 119 | 119 |
CODEC_ID_ZMBV, |
| 120 | 120 |
CODEC_ID_AVS, |
| 121 | 121 |
CODEC_ID_SMACKVIDEO, |
| 122 |
+ CODEC_ID_NUV, |
|
| 122 | 123 |
|
| 123 | 124 |
/* various pcm "codecs" */ |
| 124 | 125 |
CODEC_ID_PCM_S16LE= 0x10000, |
| ... | ... |
@@ -2221,6 +2222,7 @@ extern AVCodec qtrle_decoder; |
| 2221 | 2221 |
extern AVCodec flac_decoder; |
| 2222 | 2222 |
extern AVCodec tscc_decoder; |
| 2223 | 2223 |
extern AVCodec cscd_decoder; |
| 2224 |
+extern AVCodec nuv_decoder; |
|
| 2224 | 2225 |
extern AVCodec ulti_decoder; |
| 2225 | 2226 |
extern AVCodec qdraw_decoder; |
| 2226 | 2227 |
extern AVCodec xl_decoder; |
| 2227 | 2228 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,214 @@ |
| 0 |
+/* |
|
| 1 |
+ * NuppelVideo decoder |
|
| 2 |
+ * Copyright (c) 2006 Reimar Doeffinger |
|
| 3 |
+ * |
|
| 4 |
+ * This library is free software; you can redistribute it and/or |
|
| 5 |
+ * modify it under the terms of the GNU Lesser General Public |
|
| 6 |
+ * License as published by the Free Software Foundation; either |
|
| 7 |
+ * version 2 of the License, or (at your option) any later version. |
|
| 8 |
+ * |
|
| 9 |
+ * This library is distributed in the hope that it will be useful, |
|
| 10 |
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
| 11 |
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|
| 12 |
+ * Lesser General Public License for more details. |
|
| 13 |
+ * |
|
| 14 |
+ * You should have received a copy of the GNU Lesser General Public |
|
| 15 |
+ * License along with this library; if not, write to the Free Software |
|
| 16 |
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
|
| 17 |
+ */ |
|
| 18 |
+#include <stdio.h> |
|
| 19 |
+#include <stdlib.h> |
|
| 20 |
+ |
|
| 21 |
+#include "common.h" |
|
| 22 |
+#include "avcodec.h" |
|
| 23 |
+ |
|
| 24 |
+#include "bswap.h" |
|
| 25 |
+#include "dsputil.h" |
|
| 26 |
+#include "lzo.h" |
|
| 27 |
+#include "rtjpeg.h" |
|
| 28 |
+ |
|
| 29 |
+typedef struct {
|
|
| 30 |
+ AVFrame pic; |
|
| 31 |
+ int width, height; |
|
| 32 |
+ unsigned int decomp_size; |
|
| 33 |
+ unsigned char* decomp_buf; |
|
| 34 |
+ uint32_t lq[64], cq[64]; |
|
| 35 |
+ RTJpegContext rtj; |
|
| 36 |
+ DSPContext dsp; |
|
| 37 |
+} NuvContext; |
|
| 38 |
+ |
|
| 39 |
+/** |
|
| 40 |
+ * \brief copy frame data from buffer to AVFrame, handling stride. |
|
| 41 |
+ * \param f destination AVFrame |
|
| 42 |
+ * \param src source buffer, does not use any line-stride |
|
| 43 |
+ * \param width width of the video frame |
|
| 44 |
+ * \param height height of the video frame |
|
| 45 |
+ */ |
|
| 46 |
+static void copy_frame(AVFrame *f, uint8_t *src, |
|
| 47 |
+ int width, int height) {
|
|
| 48 |
+ AVPicture pic; |
|
| 49 |
+ avpicture_fill(&pic, src, PIX_FMT_YUV420P, width, height); |
|
| 50 |
+ img_copy((AVPicture *)f, &pic, PIX_FMT_YUV420P, width, height); |
|
| 51 |
+} |
|
| 52 |
+ |
|
| 53 |
+/** |
|
| 54 |
+ * \brief extract quantization tables from codec data into our context |
|
| 55 |
+ */ |
|
| 56 |
+static int get_quant(AVCodecContext *avctx, NuvContext *c, |
|
| 57 |
+ uint8_t *buf, int size) {
|
|
| 58 |
+ int i; |
|
| 59 |
+ if (size < 2 * 64 * 4) {
|
|
| 60 |
+ av_log(avctx, AV_LOG_ERROR, "insufficient rtjpeg quant data\n"); |
|
| 61 |
+ return -1; |
|
| 62 |
+ } |
|
| 63 |
+ for (i = 0; i < 64; i++, buf += 4) |
|
| 64 |
+ c->lq[i] = LE_32(buf); |
|
| 65 |
+ for (i = 0; i < 64; i++, buf += 4) |
|
| 66 |
+ c->cq[i] = LE_32(buf); |
|
| 67 |
+ return 0; |
|
| 68 |
+} |
|
| 69 |
+ |
|
| 70 |
+static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, |
|
| 71 |
+ uint8_t *buf, int buf_size) {
|
|
| 72 |
+ NuvContext *c = (NuvContext *)avctx->priv_data; |
|
| 73 |
+ AVFrame *picture = data; |
|
| 74 |
+ int orig_size = buf_size; |
|
| 75 |
+ enum {NUV_UNCOMPRESSED = '0', NUV_RTJPEG = '1',
|
|
| 76 |
+ NUV_RTJPEG_IN_LZO = '2', NUV_LZO = '3', |
|
| 77 |
+ NUV_BLACK = 'N', NUV_COPY_LAST = 'L'} comptype; |
|
| 78 |
+ |
|
| 79 |
+ if (buf_size < 12) {
|
|
| 80 |
+ av_log(avctx, AV_LOG_ERROR, "coded frame too small\n"); |
|
| 81 |
+ return -1; |
|
| 82 |
+ } |
|
| 83 |
+ |
|
| 84 |
+ if (c->pic.data[0]) |
|
| 85 |
+ avctx->release_buffer(avctx, &c->pic); |
|
| 86 |
+ c->pic.reference = 1; |
|
| 87 |
+ c->pic.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_READABLE | |
|
| 88 |
+ FF_BUFFER_HINTS_PRESERVE | FF_BUFFER_HINTS_REUSABLE; |
|
| 89 |
+ if (avctx->get_buffer(avctx, &c->pic) < 0) {
|
|
| 90 |
+ av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); |
|
| 91 |
+ return -1; |
|
| 92 |
+ } |
|
| 93 |
+ |
|
| 94 |
+ // codec data (rtjpeg quant tables) |
|
| 95 |
+ if (buf[0] == 'D' && buf[1] == 'R') {
|
|
| 96 |
+ int ret; |
|
| 97 |
+ // skip rest of the frameheader. |
|
| 98 |
+ buf = &buf[12]; |
|
| 99 |
+ buf_size -= 12; |
|
| 100 |
+ ret = get_quant(avctx, c, buf, buf_size); |
|
| 101 |
+ if (ret < 0) |
|
| 102 |
+ return ret; |
|
| 103 |
+ rtjpeg_decode_init(&c->rtj, &c->dsp, c->width, c->height, c->lq, c->cq); |
|
| 104 |
+ return orig_size; |
|
| 105 |
+ } |
|
| 106 |
+ |
|
| 107 |
+ if (buf[0] != 'V' || buf_size < 12) {
|
|
| 108 |
+ av_log(avctx, AV_LOG_ERROR, "not a nuv video frame\n"); |
|
| 109 |
+ return -1; |
|
| 110 |
+ } |
|
| 111 |
+ comptype = buf[1]; |
|
| 112 |
+ // skip rest of the frameheader. |
|
| 113 |
+ buf = &buf[12]; |
|
| 114 |
+ buf_size -= 12; |
|
| 115 |
+ |
|
| 116 |
+ c->pic.pict_type = FF_I_TYPE; |
|
| 117 |
+ c->pic.key_frame = 1; |
|
| 118 |
+ // decompress/copy/whatever data |
|
| 119 |
+ switch (comptype) {
|
|
| 120 |
+ case NUV_UNCOMPRESSED: {
|
|
| 121 |
+ int height = c->height; |
|
| 122 |
+ if (buf_size < c->width * height * 3 / 2) {
|
|
| 123 |
+ av_log(avctx, AV_LOG_ERROR, "uncompressed frame too short\n"); |
|
| 124 |
+ height = buf_size / c->width / 3 * 2; |
|
| 125 |
+ } |
|
| 126 |
+ copy_frame(&c->pic, buf, c->width, height); |
|
| 127 |
+ break; |
|
| 128 |
+ } |
|
| 129 |
+ case NUV_RTJPEG: {
|
|
| 130 |
+ rtjpeg_decode_frame_yuv420(&c->rtj, &c->pic, buf, buf_size); |
|
| 131 |
+ break; |
|
| 132 |
+ } |
|
| 133 |
+ case NUV_RTJPEG_IN_LZO: {
|
|
| 134 |
+ int outlen = c->decomp_size, inlen = buf_size; |
|
| 135 |
+ if (lzo1x_decode(c->decomp_buf, &outlen, buf, &inlen)) |
|
| 136 |
+ av_log(avctx, AV_LOG_ERROR, "error during lzo decompression\n"); |
|
| 137 |
+ rtjpeg_decode_frame_yuv420(&c->rtj, &c->pic, c->decomp_buf, c->decomp_size); |
|
| 138 |
+ break; |
|
| 139 |
+ } |
|
| 140 |
+ case NUV_LZO: {
|
|
| 141 |
+ int outlen = c->decomp_size, inlen = buf_size; |
|
| 142 |
+ if (lzo1x_decode(c->decomp_buf, &outlen, buf, &inlen)) |
|
| 143 |
+ av_log(avctx, AV_LOG_ERROR, "error during lzo decompression\n"); |
|
| 144 |
+ copy_frame(&c->pic, c->decomp_buf, c->width, c->height); |
|
| 145 |
+ break; |
|
| 146 |
+ } |
|
| 147 |
+ case NUV_BLACK: {
|
|
| 148 |
+ memset(c->pic.data[0], 0, c->width * c->height); |
|
| 149 |
+ memset(c->pic.data[1], 128, c->width * c->height / 4); |
|
| 150 |
+ memset(c->pic.data[2], 128, c->width * c->height / 4); |
|
| 151 |
+ break; |
|
| 152 |
+ } |
|
| 153 |
+ case NUV_COPY_LAST: {
|
|
| 154 |
+ c->pic.pict_type = FF_P_TYPE; |
|
| 155 |
+ c->pic.key_frame = 0; |
|
| 156 |
+ /* nothing more to do here */ |
|
| 157 |
+ break; |
|
| 158 |
+ } |
|
| 159 |
+ default: |
|
| 160 |
+ av_log(avctx, AV_LOG_ERROR, "unknown compression\n"); |
|
| 161 |
+ return -1; |
|
| 162 |
+ } |
|
| 163 |
+ |
|
| 164 |
+ *picture = c->pic; |
|
| 165 |
+ *data_size = sizeof(AVFrame); |
|
| 166 |
+ return orig_size; |
|
| 167 |
+} |
|
| 168 |
+ |
|
| 169 |
+static int decode_init(AVCodecContext *avctx) {
|
|
| 170 |
+ NuvContext *c = (NuvContext *)avctx->priv_data; |
|
| 171 |
+ avctx->width = (avctx->width + 1) & ~1; |
|
| 172 |
+ avctx->height = (avctx->height + 1) & ~1; |
|
| 173 |
+ if (avcodec_check_dimensions(avctx, avctx->height, avctx->width) < 0) {
|
|
| 174 |
+ return 1; |
|
| 175 |
+ } |
|
| 176 |
+ avctx->has_b_frames = 0; |
|
| 177 |
+ avctx->pix_fmt = PIX_FMT_YUV420P; |
|
| 178 |
+ c->pic.data[0] = NULL; |
|
| 179 |
+ c->width = avctx->width; |
|
| 180 |
+ c->height = avctx->height; |
|
| 181 |
+ c->decomp_size = c->height * c->width * 3 / 2; |
|
| 182 |
+ c->decomp_buf = av_malloc(c->decomp_size + LZO_OUTPUT_PADDING); |
|
| 183 |
+ if (!c->decomp_buf) {
|
|
| 184 |
+ av_log(avctx, AV_LOG_ERROR, "Can't allocate decompression buffer.\n"); |
|
| 185 |
+ return 1; |
|
| 186 |
+ } |
|
| 187 |
+ dsputil_init(&c->dsp, avctx); |
|
| 188 |
+ if (avctx->extradata_size) |
|
| 189 |
+ get_quant(avctx, c, avctx->extradata, avctx->extradata_size); |
|
| 190 |
+ rtjpeg_decode_init(&c->rtj, &c->dsp, c->width, c->height, c->lq, c->cq); |
|
| 191 |
+ return 0; |
|
| 192 |
+} |
|
| 193 |
+ |
|
| 194 |
+static int decode_end(AVCodecContext *avctx) {
|
|
| 195 |
+ NuvContext *c = (NuvContext *)avctx->priv_data; |
|
| 196 |
+ av_freep(&c->decomp_buf); |
|
| 197 |
+ if (c->pic.data[0]) |
|
| 198 |
+ avctx->release_buffer(avctx, &c->pic); |
|
| 199 |
+ return 0; |
|
| 200 |
+} |
|
| 201 |
+ |
|
| 202 |
+AVCodec nuv_decoder = {
|
|
| 203 |
+ "nuv", |
|
| 204 |
+ CODEC_TYPE_VIDEO, |
|
| 205 |
+ CODEC_ID_NUV, |
|
| 206 |
+ sizeof(NuvContext), |
|
| 207 |
+ decode_init, |
|
| 208 |
+ NULL, |
|
| 209 |
+ decode_end, |
|
| 210 |
+ decode_frame, |
|
| 211 |
+ CODEC_CAP_DR1, |
|
| 212 |
+}; |
|
| 213 |
+ |
| 0 | 214 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,162 @@ |
| 0 |
+/* |
|
| 1 |
+ * RTJpeg decoding functions |
|
| 2 |
+ * Copyright (c) 2006 Reimar Doeffinger |
|
| 3 |
+ * |
|
| 4 |
+ * This library is free software; you can redistribute it and/or |
|
| 5 |
+ * modify it under the terms of the GNU Lesser General Public |
|
| 6 |
+ * License as published by the Free Software Foundation; either |
|
| 7 |
+ * version 2 of the License, or (at your option) any later version. |
|
| 8 |
+ * |
|
| 9 |
+ * This library is distributed in the hope that it will be useful, |
|
| 10 |
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
| 11 |
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|
| 12 |
+ * Lesser General Public License for more details. |
|
| 13 |
+ * |
|
| 14 |
+ * You should have received a copy of the GNU Lesser General Public |
|
| 15 |
+ * License along with this library; if not, write to the Free Software |
|
| 16 |
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
|
| 17 |
+ */ |
|
| 18 |
+#include "common.h" |
|
| 19 |
+#include "bitstream.h" |
|
| 20 |
+#include "dsputil.h" |
|
| 21 |
+#include "rtjpeg.h" |
|
| 22 |
+ |
|
| 23 |
+#define PUT_COEFF(c) \ |
|
| 24 |
+ i = scan[coeff--]; \ |
|
| 25 |
+ block[i] = (c) * quant[i]; |
|
| 26 |
+ |
|
| 27 |
+//! aligns the bitstream to the give power of two |
|
| 28 |
+#define ALIGN(a) \ |
|
| 29 |
+ n = (-get_bits_count(gb)) & (a - 1); \ |
|
| 30 |
+ if (n) {skip_bits(gb, n);}
|
|
| 31 |
+ |
|
| 32 |
+/** |
|
| 33 |
+ * \brief read one block from stream |
|
| 34 |
+ * \param gb contains stream data |
|
| 35 |
+ * \param block where data is written to |
|
| 36 |
+ * \param scan array containing the mapping stream address -> block position |
|
| 37 |
+ * \param quant quantization factors |
|
| 38 |
+ * |
|
| 39 |
+ * Note: GetBitContext is used to make the code simpler, since all data is |
|
| 40 |
+ * aligned this could be done faster in a different way, e.g. as it is done |
|
| 41 |
+ * in MPlayer libmpcodecs/native/RTjpegN.c |
|
| 42 |
+ */ |
|
| 43 |
+static inline int get_block(GetBitContext *gb, DCTELEM *block, uint8_t *scan, |
|
| 44 |
+ uint32_t *quant) {
|
|
| 45 |
+ int coeff, i, n; |
|
| 46 |
+ int8_t ac; |
|
| 47 |
+ uint8_t dc = get_bits(gb, 8); |
|
| 48 |
+ |
|
| 49 |
+ // block not coded |
|
| 50 |
+ if (dc == 255) |
|
| 51 |
+ return 0; |
|
| 52 |
+ |
|
| 53 |
+ // number of non-zero coefficients |
|
| 54 |
+ coeff = get_bits(gb, 6); |
|
| 55 |
+ // normally we would only need to clear the (63 - coeff) last values, |
|
| 56 |
+ // but since we do not know where they are we just clear the whole block |
|
| 57 |
+ memset(block, 0, 64 * sizeof(DCTELEM)); |
|
| 58 |
+ |
|
| 59 |
+ // 2 bits per coefficient |
|
| 60 |
+ while (coeff) {
|
|
| 61 |
+ ac = get_sbits(gb, 2); |
|
| 62 |
+ if (ac == -2) |
|
| 63 |
+ break; // continue with more bits |
|
| 64 |
+ PUT_COEFF(ac); |
|
| 65 |
+ } |
|
| 66 |
+ |
|
| 67 |
+ // 4 bits per coefficient |
|
| 68 |
+ ALIGN(4); |
|
| 69 |
+ while (coeff) {
|
|
| 70 |
+ ac = get_sbits(gb, 4); |
|
| 71 |
+ if (ac == -8) |
|
| 72 |
+ break; // continue with more bits |
|
| 73 |
+ PUT_COEFF(ac); |
|
| 74 |
+ } |
|
| 75 |
+ |
|
| 76 |
+ // 8 bits per coefficient |
|
| 77 |
+ ALIGN(8); |
|
| 78 |
+ while (coeff) {
|
|
| 79 |
+ ac = get_sbits(gb, 8); |
|
| 80 |
+ PUT_COEFF(ac); |
|
| 81 |
+ } |
|
| 82 |
+ |
|
| 83 |
+ PUT_COEFF(dc); |
|
| 84 |
+ return 1; |
|
| 85 |
+} |
|
| 86 |
+ |
|
| 87 |
+/** |
|
| 88 |
+ * \brief decode one rtjpeg YUV420 frame |
|
| 89 |
+ * \param c context, must be initialized via rtjpeg_decode_init |
|
| 90 |
+ * \param f AVFrame to place decoded frame into. If parts of the frame |
|
| 91 |
+ * are not coded they are left unchanged, so consider initializing it |
|
| 92 |
+ * \param buf buffer containing input data |
|
| 93 |
+ * \param buf_size length of input data in bytes |
|
| 94 |
+ * \return number of bytes consumed from the input buffer |
|
| 95 |
+ */ |
|
| 96 |
+int rtjpeg_decode_frame_yuv420(RTJpegContext *c, AVFrame *f, |
|
| 97 |
+ uint8_t *buf, int buf_size) {
|
|
| 98 |
+ GetBitContext gb; |
|
| 99 |
+ int w = c->w / 16, h = c->h / 16; |
|
| 100 |
+ int x, y; |
|
| 101 |
+ void *y1 = f->data[0], *y2 = f->data[0] + 8 * f->linesize[0]; |
|
| 102 |
+ void *u = f->data[1], *v = f->data[2]; |
|
| 103 |
+ init_get_bits(&gb, buf, buf_size * 8); |
|
| 104 |
+ for (y = 0; y < h; y++) {
|
|
| 105 |
+ for (x = 0; x < w; x++) {
|
|
| 106 |
+ if (get_block(&gb, c->block, c->scan, c->lquant)) |
|
| 107 |
+ c->dsp->idct_put(y1, f->linesize[0], c->block); |
|
| 108 |
+ y1 += 8; |
|
| 109 |
+ if (get_block(&gb, c->block, c->scan, c->lquant)) |
|
| 110 |
+ c->dsp->idct_put(y1, f->linesize[0], c->block); |
|
| 111 |
+ y1 += 8; |
|
| 112 |
+ if (get_block(&gb, c->block, c->scan, c->lquant)) |
|
| 113 |
+ c->dsp->idct_put(y2, f->linesize[0], c->block); |
|
| 114 |
+ y2 += 8; |
|
| 115 |
+ if (get_block(&gb, c->block, c->scan, c->lquant)) |
|
| 116 |
+ c->dsp->idct_put(y2, f->linesize[0], c->block); |
|
| 117 |
+ y2 += 8; |
|
| 118 |
+ if (get_block(&gb, c->block, c->scan, c->cquant)) |
|
| 119 |
+ c->dsp->idct_put(u, f->linesize[1], c->block); |
|
| 120 |
+ u += 8; |
|
| 121 |
+ if (get_block(&gb, c->block, c->scan, c->cquant)) |
|
| 122 |
+ c->dsp->idct_put(v, f->linesize[2], c->block); |
|
| 123 |
+ v += 8; |
|
| 124 |
+ } |
|
| 125 |
+ y1 += 2 * 8 * (f->linesize[0] - w); |
|
| 126 |
+ y2 += 2 * 8 * (f->linesize[0] - w); |
|
| 127 |
+ u += 8 * (f->linesize[1] - w); |
|
| 128 |
+ v += 8 * (f->linesize[2] - w); |
|
| 129 |
+ } |
|
| 130 |
+ return get_bits_count(&gb) / 8; |
|
| 131 |
+} |
|
| 132 |
+ |
|
| 133 |
+/** |
|
| 134 |
+ * \brief initialize an RTJpegContext, may be called multiple times |
|
| 135 |
+ * \param c context to initialize |
|
| 136 |
+ * \param dsp specifies the idct to use for decoding |
|
| 137 |
+ * \param width width of image, will be rounded down to the nearest multiple |
|
| 138 |
+ * of 16 for decoding |
|
| 139 |
+ * \param height height of image, will be rounded down to the nearest multiple |
|
| 140 |
+ * of 16 for decoding |
|
| 141 |
+ * \param lquant luma quantization table to use |
|
| 142 |
+ * \param cquant chroma quantization table to use |
|
| 143 |
+ */ |
|
| 144 |
+void rtjpeg_decode_init(RTJpegContext *c, DSPContext *dsp, |
|
| 145 |
+ int width, int height, |
|
| 146 |
+ uint32_t *lquant, uint32_t *cquant) {
|
|
| 147 |
+ int i; |
|
| 148 |
+ c->dsp = dsp; |
|
| 149 |
+ for (i = 0; i < 64; i++) {
|
|
| 150 |
+ int z = ff_zigzag_direct[i]; |
|
| 151 |
+ int p = c->dsp->idct_permutation[i]; |
|
| 152 |
+ z = ((z << 3) | (z >> 3)) & 63; // rtjpeg uses a transposed variant |
|
| 153 |
+ |
|
| 154 |
+ // permute the scan and quantization tables for the chosen idct |
|
| 155 |
+ c->scan[i] = c->dsp->idct_permutation[z]; |
|
| 156 |
+ c->lquant[p] = lquant[i]; |
|
| 157 |
+ c->cquant[p] = cquant[i]; |
|
| 158 |
+ } |
|
| 159 |
+ c->w = width; |
|
| 160 |
+ c->h = height; |
|
| 161 |
+} |
| 0 | 162 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,19 @@ |
| 0 |
+#ifndef RTJPEG_H |
|
| 1 |
+#define RTJPEG_H |
|
| 2 |
+ |
|
| 3 |
+typedef struct {
|
|
| 4 |
+ int w, h; |
|
| 5 |
+ DSPContext *dsp; |
|
| 6 |
+ DCTELEM block[64]; |
|
| 7 |
+ uint8_t scan[64]; |
|
| 8 |
+ uint32_t lquant[64]; |
|
| 9 |
+ uint32_t cquant[64]; |
|
| 10 |
+} RTJpegContext; |
|
| 11 |
+ |
|
| 12 |
+void rtjpeg_decode_init(RTJpegContext *c, DSPContext *dsp, |
|
| 13 |
+ int width, int height, |
|
| 14 |
+ uint32_t *lquant, uint32_t *cquant); |
|
| 15 |
+ |
|
| 16 |
+int rtjpeg_decode_frame_yuv420(RTJpegContext *c, AVFrame *f, |
|
| 17 |
+ uint8_t *buf, int buf_size); |
|
| 18 |
+#endif |
| ... | ... |
@@ -18,7 +18,7 @@ OBJS+=mpeg.o mpegts.o mpegtsenc.o ffm.o crc.o img.o img2.o raw.o rm.o \ |
| 18 | 18 |
nut.o wc3movie.o mp3.o westwood.o segafilm.o idcin.o flic.o \ |
| 19 | 19 |
sierravmd.o matroska.o sol.o electronicarts.o nsvdec.o asf.o \ |
| 20 | 20 |
ogg2.o oggparsevorbis.o oggparsetheora.o oggparseflac.o daud.o aiff.o \ |
| 21 |
- voc.o tta.o mm.o avs.o smacker.o |
|
| 21 |
+ voc.o tta.o mm.o avs.o smacker.o nuv.o |
|
| 22 | 22 |
|
| 23 | 23 |
# muxers |
| 24 | 24 |
ifeq ($(CONFIG_MUXERS),yes) |
| 555 | 558 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,245 @@ |
| 0 |
+/* |
|
| 1 |
+ * NuppelVideo demuxer. |
|
| 2 |
+ * Copyright (c) 2006 Reimar Doeffinger. |
|
| 3 |
+ * |
|
| 4 |
+ * This library is free software; you can redistribute it and/or |
|
| 5 |
+ * modify it under the terms of the GNU Lesser General Public |
|
| 6 |
+ * License as published by the Free Software Foundation; either |
|
| 7 |
+ * version 2 of the License, or (at your option) any later version. |
|
| 8 |
+ * |
|
| 9 |
+ * This library is distributed in the hope that it will be useful, |
|
| 10 |
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
| 11 |
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|
| 12 |
+ * Lesser General Public License for more details. |
|
| 13 |
+ * |
|
| 14 |
+ * You should have received a copy of the GNU Lesser General Public |
|
| 15 |
+ * License along with this library; if not, write to the Free Software |
|
| 16 |
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
|
| 17 |
+ */ |
|
| 18 |
+#include "avformat.h" |
|
| 19 |
+#include "avi.h" |
|
| 20 |
+ |
|
| 21 |
+typedef struct {
|
|
| 22 |
+ int v_id; |
|
| 23 |
+ int a_id; |
|
| 24 |
+} NUVContext; |
|
| 25 |
+ |
|
| 26 |
+typedef enum {
|
|
| 27 |
+ NUV_VIDEO = 'V', |
|
| 28 |
+ NUV_EXTRADATA = 'D', |
|
| 29 |
+ NUV_AUDIO = 'A', |
|
| 30 |
+ NUV_SEEKP = 'R', |
|
| 31 |
+ NUV_MYTHEXT = 'X' |
|
| 32 |
+} frametype_t; |
|
| 33 |
+ |
|
| 34 |
+static int nuv_probe(AVProbeData *p) {
|
|
| 35 |
+ if (p->buf_size < 12) |
|
| 36 |
+ return 0; |
|
| 37 |
+ if (!memcmp(p->buf, "NuppelVideo", 12)) |
|
| 38 |
+ return AVPROBE_SCORE_MAX; |
|
| 39 |
+ if (!memcmp(p->buf, "MythTVVideo", 12)) |
|
| 40 |
+ return AVPROBE_SCORE_MAX; |
|
| 41 |
+ return 0; |
|
| 42 |
+} |
|
| 43 |
+ |
|
| 44 |
+//! little macro to sanitize packet size |
|
| 45 |
+#define PKTSIZE(s) (s & 0xffffff) |
|
| 46 |
+ |
|
| 47 |
+/** |
|
| 48 |
+ * \brief read until we found all data needed for decoding |
|
| 49 |
+ * \param vst video stream of which to change parameters |
|
| 50 |
+ * \param ast video stream of which to change parameters |
|
| 51 |
+ * \param myth set if this is a MythTVVideo format file |
|
| 52 |
+ * \return 1 if all required codec data was found |
|
| 53 |
+ */ |
|
| 54 |
+static int get_codec_data(ByteIOContext *pb, AVStream *vst, |
|
| 55 |
+ AVStream *ast, int myth) {
|
|
| 56 |
+ frametype_t frametype; |
|
| 57 |
+ if (!vst && !myth) |
|
| 58 |
+ return 1; // no codec data needed |
|
| 59 |
+ while (!url_feof(pb)) {
|
|
| 60 |
+ int size, subtype; |
|
| 61 |
+ frametype = get_byte(pb); |
|
| 62 |
+ switch (frametype) {
|
|
| 63 |
+ case NUV_EXTRADATA: |
|
| 64 |
+ subtype = get_byte(pb); |
|
| 65 |
+ url_fskip(pb, 6); |
|
| 66 |
+ size = PKTSIZE(get_le32(pb)); |
|
| 67 |
+ if (subtype == 'R') {
|
|
| 68 |
+ vst->codec->extradata_size = size; |
|
| 69 |
+ vst->codec->extradata = av_malloc(size); |
|
| 70 |
+ get_buffer(pb, vst->codec->extradata, size); |
|
| 71 |
+ size = 0; |
|
| 72 |
+ if (!myth) |
|
| 73 |
+ return 1; |
|
| 74 |
+ } |
|
| 75 |
+ break; |
|
| 76 |
+ case NUV_MYTHEXT: |
|
| 77 |
+ url_fskip(pb, 7); |
|
| 78 |
+ size = PKTSIZE(get_le32(pb)); |
|
| 79 |
+ if (size != 128 * 4) |
|
| 80 |
+ break; |
|
| 81 |
+ get_le32(pb); // version |
|
| 82 |
+ if (vst) {
|
|
| 83 |
+ vst->codec->codec_tag = get_le32(pb); |
|
| 84 |
+ vst->codec->codec_id = |
|
| 85 |
+ codec_get_id(codec_bmp_tags, vst->codec->codec_tag); |
|
| 86 |
+ } else |
|
| 87 |
+ url_fskip(pb, 4); |
|
| 88 |
+ |
|
| 89 |
+ if (ast) {
|
|
| 90 |
+ ast->codec->codec_tag = get_le32(pb); |
|
| 91 |
+ ast->codec->sample_rate = get_le32(pb); |
|
| 92 |
+ ast->codec->bits_per_sample = get_le32(pb); |
|
| 93 |
+ ast->codec->channels = get_le32(pb); |
|
| 94 |
+ ast->codec->codec_id = |
|
| 95 |
+ wav_codec_get_id(ast->codec->codec_tag, |
|
| 96 |
+ ast->codec->bits_per_sample); |
|
| 97 |
+ } else |
|
| 98 |
+ url_fskip(pb, 4 * 4); |
|
| 99 |
+ |
|
| 100 |
+ size -= 6 * 4; |
|
| 101 |
+ url_fskip(pb, size); |
|
| 102 |
+ return 1; |
|
| 103 |
+ case NUV_SEEKP: |
|
| 104 |
+ size = 11; |
|
| 105 |
+ break; |
|
| 106 |
+ default: |
|
| 107 |
+ url_fskip(pb, 7); |
|
| 108 |
+ size = PKTSIZE(get_le32(pb)); |
|
| 109 |
+ break; |
|
| 110 |
+ } |
|
| 111 |
+ url_fskip(pb, size); |
|
| 112 |
+ } |
|
| 113 |
+ return 0; |
|
| 114 |
+} |
|
| 115 |
+ |
|
| 116 |
+static int nuv_header(AVFormatContext *s, AVFormatParameters *ap) {
|
|
| 117 |
+ NUVContext *ctx = (NUVContext *)s->priv_data; |
|
| 118 |
+ ByteIOContext *pb = &s->pb; |
|
| 119 |
+ char id_string[12], version_string[5]; |
|
| 120 |
+ double aspect, fps; |
|
| 121 |
+ int is_mythtv, width, height, v_packs, a_packs; |
|
| 122 |
+ int stream_nr = 0; |
|
| 123 |
+ AVStream *vst = NULL, *ast = NULL; |
|
| 124 |
+ get_buffer(pb, id_string, 12); |
|
| 125 |
+ is_mythtv = !memcmp(id_string, "MythTVVideo", 12); |
|
| 126 |
+ get_buffer(pb, version_string, 5); |
|
| 127 |
+ url_fskip(pb, 3); // padding |
|
| 128 |
+ width = get_le32(pb); |
|
| 129 |
+ height = get_le32(pb); |
|
| 130 |
+ get_le32(pb); // unused, "desiredwidth" |
|
| 131 |
+ get_le32(pb); // unused, "desiredheight" |
|
| 132 |
+ get_byte(pb); // 'P' == progressive, 'I' == interlaced |
|
| 133 |
+ url_fskip(pb, 3); // padding |
|
| 134 |
+ aspect = av_int2dbl(get_le64(pb)); |
|
| 135 |
+ fps = av_int2dbl(get_le64(pb)); |
|
| 136 |
+ |
|
| 137 |
+ // number of packets per stream type, -1 means unknown, e.g. streaming |
|
| 138 |
+ v_packs = get_le32(pb); |
|
| 139 |
+ a_packs = get_le32(pb); |
|
| 140 |
+ get_le32(pb); // text |
|
| 141 |
+ |
|
| 142 |
+ get_le32(pb); // keyframe distance (?) |
|
| 143 |
+ |
|
| 144 |
+ if (v_packs) {
|
|
| 145 |
+ ctx->v_id = stream_nr++; |
|
| 146 |
+ vst = av_new_stream(s, ctx->v_id); |
|
| 147 |
+ vst->codec->codec_type = CODEC_TYPE_VIDEO; |
|
| 148 |
+ vst->codec->codec_id = CODEC_ID_NUV; |
|
| 149 |
+ vst->codec->codec_tag = MKTAG('R', 'J', 'P', 'G');
|
|
| 150 |
+ vst->codec->width = width; |
|
| 151 |
+ vst->codec->height = height; |
|
| 152 |
+ vst->codec->bits_per_sample = 10; |
|
| 153 |
+ vst->codec->sample_aspect_ratio = av_d2q(aspect, 10000); |
|
| 154 |
+ vst->r_frame_rate = av_d2q(1.0 / fps, 10000); |
|
| 155 |
+ av_set_pts_info(vst, 32, 1, 1000); |
|
| 156 |
+ } else |
|
| 157 |
+ ctx->v_id = -1; |
|
| 158 |
+ |
|
| 159 |
+ if (a_packs) {
|
|
| 160 |
+ ctx->a_id = stream_nr++; |
|
| 161 |
+ ast = av_new_stream(s, ctx->a_id); |
|
| 162 |
+ ast->codec->codec_type = CODEC_TYPE_AUDIO; |
|
| 163 |
+ ast->codec->codec_id = CODEC_ID_PCM_S16LE; |
|
| 164 |
+ ast->codec->channels = 2; |
|
| 165 |
+ ast->codec->sample_rate = 44100; |
|
| 166 |
+ ast->codec->bit_rate = 2 * 2 * 44100 * 8; |
|
| 167 |
+ ast->codec->block_align = 2 * 2; |
|
| 168 |
+ ast->codec->bits_per_sample = 16; |
|
| 169 |
+ av_set_pts_info(ast, 32, 1, 1000); |
|
| 170 |
+ } else |
|
| 171 |
+ ctx->a_id = -1; |
|
| 172 |
+ |
|
| 173 |
+ get_codec_data(pb, vst, ast, is_mythtv); |
|
| 174 |
+ return 0; |
|
| 175 |
+} |
|
| 176 |
+ |
|
| 177 |
+#define HDRSIZE 12 |
|
| 178 |
+ |
|
| 179 |
+static int nuv_packet(AVFormatContext *s, AVPacket *pkt) {
|
|
| 180 |
+ NUVContext *ctx = (NUVContext *)s->priv_data; |
|
| 181 |
+ ByteIOContext *pb = &s->pb; |
|
| 182 |
+ uint8_t hdr[HDRSIZE]; |
|
| 183 |
+ frametype_t frametype; |
|
| 184 |
+ int ret, size; |
|
| 185 |
+ while (!url_feof(pb)) {
|
|
| 186 |
+ ret = get_buffer(pb, hdr, HDRSIZE); |
|
| 187 |
+ if (ret <= 0) |
|
| 188 |
+ return ret; |
|
| 189 |
+ frametype = hdr[0]; |
|
| 190 |
+ size = PKTSIZE(LE_32(&hdr[8])); |
|
| 191 |
+ switch (frametype) {
|
|
| 192 |
+ case NUV_VIDEO: |
|
| 193 |
+ case NUV_EXTRADATA: |
|
| 194 |
+ if (ctx->v_id < 0) {
|
|
| 195 |
+ av_log(s, AV_LOG_ERROR, "Video packet in file without video stream!\n"); |
|
| 196 |
+ url_fskip(pb, size); |
|
| 197 |
+ break; |
|
| 198 |
+ } |
|
| 199 |
+ ret = av_new_packet(pkt, HDRSIZE + size); |
|
| 200 |
+ if (ret < 0) |
|
| 201 |
+ return ret; |
|
| 202 |
+ pkt->pos = url_ftell(pb); |
|
| 203 |
+ pkt->pts = LE_32(&hdr[4]); |
|
| 204 |
+ pkt->stream_index = ctx->v_id; |
|
| 205 |
+ memcpy(pkt->data, hdr, HDRSIZE); |
|
| 206 |
+ ret = get_buffer(pb, pkt->data + HDRSIZE, size); |
|
| 207 |
+ return ret; |
|
| 208 |
+ case NUV_AUDIO: |
|
| 209 |
+ if (ctx->a_id < 0) {
|
|
| 210 |
+ av_log(s, AV_LOG_ERROR, "Audio packet in file without audio stream!\n"); |
|
| 211 |
+ url_fskip(pb, size); |
|
| 212 |
+ break; |
|
| 213 |
+ } |
|
| 214 |
+ ret = av_get_packet(pb, pkt, size); |
|
| 215 |
+ pkt->pts = LE_32(&hdr[4]); |
|
| 216 |
+ pkt->stream_index = ctx->a_id; |
|
| 217 |
+ return ret; |
|
| 218 |
+ case NUV_SEEKP: |
|
| 219 |
+ // contains no data, size value is invalid |
|
| 220 |
+ break; |
|
| 221 |
+ default: |
|
| 222 |
+ url_fskip(pb, size); |
|
| 223 |
+ break; |
|
| 224 |
+ } |
|
| 225 |
+ } |
|
| 226 |
+ return AVERROR_IO; |
|
| 227 |
+} |
|
| 228 |
+ |
|
| 229 |
+static AVInputFormat nuv_iformat = {
|
|
| 230 |
+ "nuv", |
|
| 231 |
+ "NuppelVideo format", |
|
| 232 |
+ sizeof(NUVContext), |
|
| 233 |
+ nuv_probe, |
|
| 234 |
+ nuv_header, |
|
| 235 |
+ nuv_packet, |
|
| 236 |
+ NULL, |
|
| 237 |
+ NULL, |
|
| 238 |
+}; |
|
| 239 |
+ |
|
| 240 |
+int nuv_init(void) {
|
|
| 241 |
+ av_register_input_format(&nuv_iformat); |
|
| 242 |
+ return 0; |
|
| 243 |
+} |
|
| 244 |
+ |
| ... | ... |
@@ -45,6 +45,10 @@ const CodecTag codec_wav_tags[] = {
|
| 45 | 45 |
{ CODEC_ID_ADPCM_CT, 0x200 },
|
| 46 | 46 |
{ CODEC_ID_ADPCM_SWF, ('S'<<8)+'F' },
|
| 47 | 47 |
{ CODEC_ID_TRUESPEECH, 0x22 },
|
| 48 |
+ |
|
| 49 |
+ // for NuppelVideo (nuv.c) |
|
| 50 |
+ { CODEC_ID_PCM_S16LE, MKTAG('R', 'A', 'W', 'A') },
|
|
| 51 |
+ { CODEC_ID_MP3, MKTAG('L', 'A', 'M', 'E') },
|
|
| 48 | 52 |
{ 0, 0 },
|
| 49 | 53 |
}; |
| 50 | 54 |
|