]> git.sesse.net Git - ffmpeg/blob - libavcodec/avrndec.c
Merge commit '8e134e5104e99a69cd4cea10540a7ce9c3682a2c'
[ffmpeg] / libavcodec / avrndec.c
1 /*
2  * AVRn decoder
3  * Copyright (c) 2012 Michael Niedermayer
4  *
5  * This file is part of FFmpeg.
6  *
7  * FFmpeg is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * FFmpeg is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with FFmpeg; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21
22 #include "avcodec.h"
23 #include "mjpeg.h"
24 #include "mjpegdec.h"
25 #include "libavutil/imgutils.h"
26
27 typedef struct {
28     MJpegDecodeContext mjpeg_ctx;
29     AVFrame frame;
30     int is_mjpeg;
31     int interlace; //FIXME use frame.interlaced_frame
32     int tff;
33 } AVRnContext;
34
35 static av_cold int init(AVCodecContext *avctx)
36 {
37     AVRnContext *a = avctx->priv_data;
38     int ret;
39
40     // Support "Resolution 1:1" for Avid AVI Codec
41     a->is_mjpeg = avctx->extradata_size < 31 || memcmp(&avctx->extradata[28], "1:1", 3);
42
43     if(!a->is_mjpeg && avctx->lowres) {
44         av_log(avctx, AV_LOG_ERROR, "lowres is not possible with rawvideo\n");
45         return AVERROR(EINVAL);
46     }
47
48     if(a->is_mjpeg)
49         return ff_mjpeg_decode_init(avctx);
50
51     if ((ret = av_image_check_size(avctx->width, avctx->height, 0, avctx)) < 0)
52         return ret;
53
54     avcodec_get_frame_defaults(&a->frame);
55     avctx->pix_fmt = AV_PIX_FMT_UYVY422;
56
57     if(avctx->extradata_size >= 9 && avctx->extradata[4]+28 < avctx->extradata_size) {
58         int ndx = avctx->extradata[4] + 4;
59         a->interlace = !memcmp(avctx->extradata + ndx, "1:1(", 4);
60         if(a->interlace) {
61             a->tff = avctx->extradata[ndx + 24] == 1;
62         }
63     }
64
65     return 0;
66 }
67
68 static av_cold int end(AVCodecContext *avctx)
69 {
70     AVRnContext *a = avctx->priv_data;
71     AVFrame *p = &a->frame;
72
73     if(p->data[0])
74         avctx->release_buffer(avctx, p);
75
76     if(a->is_mjpeg)
77         ff_mjpeg_decode_end(avctx);
78
79     return 0;
80 }
81
82 static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, AVPacket *avpkt)
83 {
84     AVRnContext *a = avctx->priv_data;
85     AVFrame *p = &a->frame;
86     const uint8_t *buf = avpkt->data;
87     int buf_size       = avpkt->size;
88     int y, ret, true_height;
89
90     if(a->is_mjpeg)
91         return ff_mjpeg_decode_frame(avctx, data, data_size, avpkt);
92
93     true_height    = buf_size / (2*avctx->width);
94     if(p->data[0])
95         avctx->release_buffer(avctx, p);
96
97     if(buf_size < 2*avctx->width * avctx->height) {
98         av_log(avctx, AV_LOG_ERROR, "packet too small\n");
99         return AVERROR_INVALIDDATA;
100     }
101
102     if((ret = avctx->get_buffer(avctx, p)) < 0){
103         av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
104         return ret;
105     }
106     p->pict_type= AV_PICTURE_TYPE_I;
107     p->key_frame= 1;
108
109     if(a->interlace) {
110         buf += (true_height - avctx->height)*avctx->width;
111         for(y = 0; y < avctx->height-1; y+=2) {
112             memcpy(p->data[0] + (y+ a->tff)*p->linesize[0], buf                             , 2*avctx->width);
113             memcpy(p->data[0] + (y+!a->tff)*p->linesize[0], buf + avctx->width*true_height+4, 2*avctx->width);
114             buf += 2*avctx->width;
115         }
116     } else {
117         buf += (true_height - avctx->height)*avctx->width*2;
118         for(y = 0; y < avctx->height; y++) {
119             memcpy(p->data[0] + y*p->linesize[0], buf, 2*avctx->width);
120             buf += 2*avctx->width;
121         }
122     }
123
124     *(AVFrame*)data = a->frame;
125     *data_size      = sizeof(AVFrame);
126     return buf_size;
127 }
128
129 AVCodec ff_avrn_decoder = {
130     .name           = "avrn",
131     .type           = AVMEDIA_TYPE_VIDEO,
132     .id             = AV_CODEC_ID_AVRN,
133     .priv_data_size = sizeof(AVRnContext),
134     .init           = init,
135     .close          = end,
136     .decode         = decode_frame,
137     .long_name      = NULL_IF_CONFIG_SMALL("Avid AVI Codec"),
138     .capabilities   = CODEC_CAP_DR1,
139     .max_lowres     = 3,
140 };
141