segfault fix
[ffmpeg.git] / libavcodec / raw.c
1 /*
2  * Raw Video Codec
3  * Copyright (c) 2001 Fabrice Bellard.
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18  */
19  
20 /**
21  * @file raw.c
22  * Raw Video Codec
23  */
24  
25 #include "avcodec.h"
26
27
28 typedef struct PixleFormatTag {
29     int pix_fmt;
30     unsigned int fourcc;
31 } PixelFormatTag;
32
33 const PixelFormatTag pixelFormatTags[] = {
34     { PIX_FMT_YUV422, MKTAG('Y', '4', '2', '2') },
35     { PIX_FMT_YUV420P, MKTAG('I', '4', '2', '0') },
36     { -1, 0 },
37 };
38
39 static int findPixelFormat(unsigned int fourcc)
40 {
41     const PixelFormatTag * tags = pixelFormatTags;
42     while (tags->pix_fmt >= 0) {
43         if (tags->fourcc == fourcc)
44             return tags->pix_fmt;
45         tags++;
46     }
47     return PIX_FMT_YUV420P;
48 }
49
50
51 typedef struct RawVideoContext {
52     unsigned char * buffer;  /* block of memory for holding one frame */
53     unsigned char * p;       /* current position in buffer */
54     int             length;  /* number of bytes in buffer */
55     AVFrame pic;             ///< AVCodecContext.coded_frame
56 } RawVideoContext;
57
58
59 static int raw_init(AVCodecContext *avctx)
60 {
61     RawVideoContext *context = avctx->priv_data;
62
63     if (avctx->codec_tag) {
64             avctx->pix_fmt = findPixelFormat(avctx->codec_tag);
65     }
66
67         context->length = avpicture_get_size(avctx->pix_fmt, avctx->width, avctx->height);
68         context->buffer = av_malloc(context->length);
69         context->p      = context->buffer;
70
71     context->pic.pict_type= FF_I_TYPE;
72     context->pic.key_frame= 1;
73     avctx->coded_frame= &context->pic;
74     
75     if (! context->buffer) {
76         return -1;
77     }
78
79     return 0;
80 }
81
82 static int raw_decode(AVCodecContext *avctx,
83                             void *data, int *data_size,
84                             uint8_t *buf, int buf_size)
85 {
86     RawVideoContext *context = avctx->priv_data;
87     int bytesNeeded;
88
89     AVPicture * picture = (AVPicture *) data;
90
91     /* Early out without copy if packet size == frame size */
92     if (buf_size == context->length  &&  context->p == context->buffer) {
93         avpicture_fill(picture, buf, avctx->pix_fmt, avctx->width, avctx->height);
94         *data_size = sizeof(AVPicture);
95         return buf_size;
96     }
97
98     bytesNeeded = context->length - (context->p - context->buffer);
99     if (buf_size < bytesNeeded) {
100         memcpy(context->p, buf, buf_size);
101         context->p += buf_size;
102         *data_size = 0;
103         return buf_size;
104     }
105
106     memcpy(context->p, buf, bytesNeeded);
107     context->p = context->buffer;
108     avpicture_fill(picture, context->buffer, avctx->pix_fmt, avctx->width, avctx->height);
109     *data_size = sizeof(AVPicture);
110     return bytesNeeded;
111 }
112
113 static int raw_close(AVCodecContext *avctx)
114 {
115     RawVideoContext *context = avctx->priv_data;
116
117     av_freep(& context->buffer);
118
119     return 0;
120 }
121
122 static int raw_encode(AVCodecContext *avctx,
123                             unsigned char *frame, int buf_size, void *data)
124 {
125         AVPicture * picture = data;
126
127     unsigned char *src;
128         unsigned char *dest = frame;
129     int i, j;
130
131         int w = avctx->width;
132         int h = avctx->height;
133         int size = avpicture_get_size(avctx->pix_fmt, w, h);
134
135     if (size > buf_size) {
136         return -1;
137     }
138
139     switch(avctx->pix_fmt) {
140     case PIX_FMT_YUV420P:
141         for(i=0;i<3;i++) {
142             if (i == 1) {
143                 w >>= 1;
144                 h >>= 1;
145             }
146             src = picture->data[i];
147             for(j=0;j<h;j++) {
148                 memcpy(dest, src, w);
149                 dest += w;
150                 src += picture->linesize[i];
151             }
152         }
153         break;
154     case PIX_FMT_YUV422P:
155         for(i=0;i<3;i++) {
156             if (i == 1) {
157                 w >>= 1;
158             }
159             src = picture->data[i];
160             for(j=0;j<h;j++) {
161                 memcpy(dest, src, w);
162                 dest += w;
163                 src += picture->linesize[i];
164             }
165         }
166         break;
167     case PIX_FMT_YUV444P:
168         for(i=0;i<3;i++) {
169             src = picture->data[i];
170             for(j=0;j<h;j++) {
171                 memcpy(dest, src, w);
172                 dest += w;
173                 src += picture->linesize[i];
174             }
175         }
176         break;
177     case PIX_FMT_YUV422:
178         src = picture->data[0];
179         for(j=0;j<h;j++) {
180             memcpy(dest, src, w * 2);
181             dest += w * 2;
182             src += picture->linesize[0];
183         }
184         break;
185     case PIX_FMT_RGB24:
186     case PIX_FMT_BGR24:
187         src = picture->data[0];
188         for(j=0;j<h;j++) {
189             memcpy(dest, src, w * 3);
190             dest += w * 3;
191             src += picture->linesize[0];
192         }
193         break;
194     default:
195         return -1;
196     }
197
198     return size;
199 }
200
201
202 AVCodec rawvideo_codec = {
203     "rawvideo",
204     CODEC_TYPE_VIDEO,
205     CODEC_ID_RAWVIDEO,
206     sizeof(RawVideoContext),
207     raw_init,
208     raw_encode,
209     raw_close,
210     raw_decode,
211 };