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