lavc: move AVRn to a seperate decoder.
authorMichael Niedermayer <michaelni@gmx.at>
Mon, 20 Aug 2012 00:19:37 +0000 (02:19 +0200)
committerMichael Niedermayer <michaelni@gmx.at>
Mon, 20 Aug 2012 00:46:09 +0000 (02:46 +0200)
The special cases in demuxers and decoders are a mess otherwise (and more
would be needed to support it fully)

Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
libavcodec/Makefile
libavcodec/allcodecs.c
libavcodec/avcodec.h
libavcodec/avrndec.c [new file with mode: 0644]
libavcodec/codec_desc.c
libavcodec/rawdec.c
libavformat/avidec.c
libavformat/riff.c

index 576ec5f..e4113da 100644 (file)
@@ -112,6 +112,7 @@ OBJS-$(CONFIG_ATRAC1_DECODER)          += atrac1.o atrac.o
 OBJS-$(CONFIG_ATRAC3_DECODER)          += atrac3.o atrac.o
 OBJS-$(CONFIG_AURA_DECODER)            += cyuv.o
 OBJS-$(CONFIG_AURA2_DECODER)           += aura.o
+OBJS-$(CONFIG_AVRP_DECODER)            += avrndec.o
 OBJS-$(CONFIG_AVRP_DECODER)            += r210dec.o
 OBJS-$(CONFIG_AVRP_ENCODER)            += r210enc.o
 OBJS-$(CONFIG_AVS_DECODER)             += avs.o
index 4a247c4..00f44a5 100644 (file)
@@ -81,6 +81,7 @@ void avcodec_register_all(void)
     REGISTER_DECODER (AURA, aura);
     REGISTER_DECODER (AURA2, aura2);
     REGISTER_ENCDEC  (AVRP, avrp);
+    REGISTER_DECODER (AVRN, avrn);
     REGISTER_DECODER (AVS, avs);
     REGISTER_ENCDEC  (AVUI, avui);
     REGISTER_ENCDEC  (AYUV, ayuv);
index 1115caf..c3cde34 100644 (file)
@@ -276,6 +276,7 @@ enum AVCodecID {
     AV_CODEC_ID_YUV4       = MKBETAG('Y','U','V','4'),
     AV_CODEC_ID_SANM       = MKBETAG('S','A','N','M'),
     AV_CODEC_ID_PAF_VIDEO  = MKBETAG('P','A','F','V'),
+    AV_CODEC_ID_AVRN       = MKBETAG('A','V','R','n'),
 
     /* various PCM "codecs" */
     AV_CODEC_ID_FIRST_AUDIO = 0x10000,     ///< A dummy id pointing at the start of audio codecs
diff --git a/libavcodec/avrndec.c b/libavcodec/avrndec.c
new file mode 100644 (file)
index 0000000..b173c6d
--- /dev/null
@@ -0,0 +1,129 @@
+/*
+ * AVRn decoder
+ * Copyright (c) 2012 Michael Niedermayer
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "avcodec.h"
+#include "mjpeg.h"
+#include "mjpegdec.h"
+
+typedef struct {
+    MJpegDecodeContext mjpeg_ctx;
+    AVFrame frame;
+    int is_mjpeg;
+    int interlace; //FIXME use frame.interlaced_frame
+    int tff;
+} AVRnContext;
+
+static av_cold int init(AVCodecContext *avctx)
+{
+    AVRnContext *a = avctx->priv_data;
+
+    // Support "Resolution 1:1" for Avid AVI Codec
+    a->is_mjpeg = avctx->extradata_size < 31 || memcmp(&avctx->extradata[28], "1:1", 3);
+
+    if(a->is_mjpeg)
+        return ff_mjpeg_decode_init(avctx);
+
+    if(avctx->width <= 0 || avctx->height <= 0)
+        return -1;
+
+    avcodec_get_frame_defaults(&a->frame);
+    avctx->pix_fmt = PIX_FMT_UYVY422;
+
+    if(avctx->extradata_size >= 9 && avctx->extradata[4]+28 < avctx->extradata_size) {
+        int ndx = avctx->extradata[4] + 4;
+        a->interlace = !memcmp(avctx->extradata + ndx, "1:1(", 4);
+        if(a->interlace) {
+            a->tff = avctx->extradata[ndx + 24] == 1;
+        }
+    }
+
+    return 0;
+}
+
+static av_cold void end(AVCodecContext *avctx)
+{
+    AVRnContext *a = avctx->priv_data;
+    AVFrame *p = &a->frame;
+
+    if(p->data[0])
+        avctx->release_buffer(avctx, p);
+
+    if(a->is_mjpeg)
+        ff_mjpeg_decode_end(avctx);
+}
+
+static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, AVPacket *avpkt)
+{
+    AVRnContext *a = avctx->priv_data;
+    AVFrame *p = &a->frame;
+    const uint8_t *buf = avpkt->data;
+    int buf_size       = avpkt->size;
+    int y;
+
+    if(a->is_mjpeg)
+        return ff_mjpeg_decode_frame(avctx, data, data_size, avpkt);
+
+    if(p->data[0])
+        avctx->release_buffer(avctx, p);
+
+    if(buf_size < 2*avctx->width * avctx->height) {
+        av_log(avctx, AV_LOG_ERROR, "packet too small\n");
+        return AVERROR_INVALIDDATA;
+    }
+
+    if(avctx->get_buffer(avctx, p) < 0){
+        av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
+        return -1;
+    }
+    p->pict_type= AV_PICTURE_TYPE_I;
+    p->key_frame= 1;
+
+    if(a->interlace) {
+        int true_height = buf_size / (2*avctx->width);
+        buf += (true_height - avctx->height)*avctx->width;
+        for(y = 0; y < avctx->height-1; y+=2) {
+            memcpy(p->data[0] + (y+ a->tff)*p->linesize[0], buf                             , 2*avctx->width);
+            memcpy(p->data[0] + (y+!a->tff)*p->linesize[0], buf + avctx->width*true_height+4, 2*avctx->width);
+            buf += 2*avctx->width;
+        }
+    } else {
+        for(y = 0; y < avctx->height; y++) {
+            memcpy(p->data[0] + y*p->linesize[0], buf, 2*avctx->width);
+            buf += 2*avctx->width;
+        }
+    }
+
+    *(AVFrame*)data = a->frame;
+    *data_size      = sizeof(AVFrame);
+    return buf_size;
+}
+
+AVCodec ff_avrn_decoder = {
+    .name           = "AVRn",
+    .type           = AVMEDIA_TYPE_VIDEO,
+    .id             = AV_CODEC_ID_AVRN,
+    .priv_data_size = sizeof(AVRnContext),
+    .init           = init,
+    .close          = end,
+    .decode         = decode_frame,
+    .long_name      = NULL_IF_CONFIG_SMALL("AVRn"),
+};
+
index 607eaab..68e07bb 100644 (file)
@@ -1175,6 +1175,12 @@ static const AVCodecDescriptor codec_descriptors[] = {
         .name      = "paf_video",
         .long_name = NULL_IF_CONFIG_SMALL("Amazing Studio Packed Animation File Video"),
     },
+    {
+        .id        = AV_CODEC_ID_AVRN,
+        .type      = AVMEDIA_TYPE_VIDEO,
+        .name      = "AVRn",
+        .long_name = NULL_IF_CONFIG_SMALL("AVRn"),
+    },
 
     /* various PCM "codecs" */
     {
index 9e2fbaa..9920e78 100644 (file)
@@ -39,7 +39,6 @@ typedef struct RawVideoContext {
     unsigned char * buffer;  /* block of memory for holding one frame */
     int             length;  /* number of bytes in buffer */
     int flip;
-    int interlace;
     AVFrame pic;             ///< AVCodecContext.coded_frame
     int tff;
 } RawVideoContext;
@@ -131,17 +130,6 @@ static av_cold int raw_init_decoder(AVCodecContext *avctx)
         avctx->codec_tag == MKTAG(3, 0, 0, 0) || avctx->codec_tag == MKTAG('W','R','A','W'))
         context->flip=1;
 
-    if(avctx->extradata_size >= 9 && avctx->extradata[4]+28 < avctx->extradata_size && !context->buffer && avctx->pix_fmt == PIX_FMT_UYVY422) {
-        int ndx = avctx->extradata[4] + 4;
-        context->interlace = !memcmp(avctx->extradata + ndx, "1:1(", 4);
-        if(context->interlace) {
-            context->buffer = av_malloc(context->length);
-            if (!context->buffer)
-                return AVERROR(ENOMEM);
-            context->tff = avctx->extradata[ndx + 24] == 1;
-        }
-    }
-
     return 0;
 }
 
@@ -185,41 +173,23 @@ static int raw_decode(AVCodecContext *avctx,
     if (context->buffer) {
         int i;
         uint8_t *dst = context->buffer;
-        if(avctx->pix_fmt == PIX_FMT_PAL8){
-            buf_size = context->length - AVPALETTE_SIZE;
-            if (avctx->bits_per_coded_sample == 4){
-                for(i=0; 2*i+1 < buf_size && i<avpkt->size; i++){
-                    dst[2*i+0]= buf[i]>>4;
-                    dst[2*i+1]= buf[i]&15;
-                }
-                linesize_align = 8;
-            } else {
-                av_assert0(avctx->bits_per_coded_sample == 2);
-                for(i=0; 4*i+3 < buf_size && i<avpkt->size; i++){
-                    dst[4*i+0]= buf[i]>>6;
-                    dst[4*i+1]= buf[i]>>4&3;
-                    dst[4*i+2]= buf[i]>>2&3;
-                    dst[4*i+3]= buf[i]   &3;
-                }
-                linesize_align = 16;
+        buf_size = context->length - AVPALETTE_SIZE;
+        if (avctx->bits_per_coded_sample == 4){
+            for(i=0; 2*i+1 < buf_size && i<avpkt->size; i++){
+                dst[2*i+0]= buf[i]>>4;
+                dst[2*i+1]= buf[i]&15;
             }
-        } else if(context->interlace && avctx->pix_fmt == PIX_FMT_UYVY422) {
-            int x, y;
-            int true_height = buf_size / (2*avctx->width);
-            int tff = !!context->tff;
-            av_assert0(avctx->height * avctx->width * 2 == context->length);
-            if (buf_size < context->length) {
-                av_log(avctx, AV_LOG_ERROR, "Invalid buffer size, packet size %d < context length %d\n", buf_size, context->length);
-                return AVERROR(EINVAL);
+            linesize_align = 8;
+        } else {
+            av_assert0(avctx->bits_per_coded_sample == 2);
+            for(i=0; 4*i+3 < buf_size && i<avpkt->size; i++){
+                dst[4*i+0]= buf[i]>>6;
+                dst[4*i+1]= buf[i]>>4&3;
+                dst[4*i+2]= buf[i]>>2&3;
+                dst[4*i+3]= buf[i]   &3;
             }
-            buf += (true_height - avctx->height)*avctx->width;
-            for(y = 0; y < avctx->height-1; y+=2) {
-                memcpy(dst + (y+ tff)*2*avctx->width, buf                             , 2*avctx->width);
-                memcpy(dst + (y+!tff)*2*avctx->width, buf + avctx->width*true_height+4, 2*avctx->width);
-                buf += 2*avctx->width;
-            }
-        }else
-            av_assert0(0);
+            linesize_align = 16;
+        }
         buf= dst;
     }
 
index d3bb8d8..a70a011 100644 (file)
@@ -635,11 +635,6 @@ static int avi_read_header(AVFormatContext *s)
                     st->codec->codec_tag = tag1;
                     st->codec->codec_id = ff_codec_get_id(ff_codec_bmp_tags, tag1);
                     st->need_parsing = AVSTREAM_PARSE_HEADERS; // This is needed to get the pict type which is necessary for generating correct pts.
-                    // Support "Resolution 1:1" for Avid AVI Codec
-                    if(tag1 == MKTAG('A', 'V', 'R', 'n') &&
-                       st->codec->extradata_size >= 31 &&
-                       !memcmp(&st->codec->extradata[28], "1:1", 3))
-                        st->codec->codec_id = AV_CODEC_ID_RAWVIDEO;
 
                     if(st->codec->codec_tag==0 && st->codec->height > 0 && st->codec->extradata_size < 1U<<30){
                         st->codec->extradata_size+= 9;
index 2152c0f..77dc797 100644 (file)
@@ -154,7 +154,7 @@ const AVCodecTag ff_codec_bmp_tags[] = {
     { AV_CODEC_ID_MJPEG,        MKTAG('M', 'J', 'L', 'S') }, /* JPEG-LS custom FOURCC for avi - decoder */
     { AV_CODEC_ID_MJPEG,        MKTAG('j', 'p', 'e', 'g') },
     { AV_CODEC_ID_MJPEG,        MKTAG('I', 'J', 'P', 'G') },
-    { AV_CODEC_ID_MJPEG,        MKTAG('A', 'V', 'R', 'n') },
+    { AV_CODEC_ID_AVRN,         MKTAG('A', 'V', 'R', 'n') },
     { AV_CODEC_ID_MJPEG,        MKTAG('A', 'C', 'D', 'V') },
     { AV_CODEC_ID_MJPEG,        MKTAG('Q', 'I', 'V', 'G') },
     { AV_CODEC_ID_MJPEG,        MKTAG('S', 'L', 'M', 'J') }, /* SL M-JPEG */