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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
---|
18 | */
|
---|
19 |
|
---|
20 | /**
|
---|
21 | * @file raw.c
|
---|
22 | * Raw Video Codec
|
---|
23 | */
|
---|
24 |
|
---|
25 | #include "avcodec.h"
|
---|
26 |
|
---|
27 | typedef struct RawVideoContext {
|
---|
28 | unsigned char * buffer; /* block of memory for holding one frame */
|
---|
29 | int length; /* number of bytes in buffer */
|
---|
30 | AVFrame pic; ///< AVCodecContext.coded_frame
|
---|
31 | } RawVideoContext;
|
---|
32 |
|
---|
33 | typedef struct PixelFormatTag {
|
---|
34 | int pix_fmt;
|
---|
35 | unsigned int fourcc;
|
---|
36 | } PixelFormatTag;
|
---|
37 |
|
---|
38 | const PixelFormatTag pixelFormatTags[] = {
|
---|
39 | { PIX_FMT_YUV420P, MKTAG('I', '4', '2', '0') }, /* Planar formats */
|
---|
40 | { PIX_FMT_YUV420P, MKTAG('I', 'Y', 'U', 'V') },
|
---|
41 | { PIX_FMT_YUV410P, MKTAG('Y', 'U', 'V', '9') },
|
---|
42 | { PIX_FMT_YUV411P, MKTAG('Y', '4', '1', 'B') },
|
---|
43 | { PIX_FMT_YUV422P, MKTAG('Y', '4', '2', 'B') },
|
---|
44 | { PIX_FMT_GRAY8, MKTAG('Y', '8', '0', '0') },
|
---|
45 | { PIX_FMT_GRAY8, MKTAG(' ', ' ', 'Y', '8') },
|
---|
46 |
|
---|
47 |
|
---|
48 | { PIX_FMT_YUV422, MKTAG('Y', 'U', 'Y', '2') }, /* Packed formats */
|
---|
49 | { PIX_FMT_YUV422, MKTAG('Y', '4', '2', '2') },
|
---|
50 | { PIX_FMT_UYVY422, MKTAG('U', 'Y', 'V', 'Y') },
|
---|
51 | { PIX_FMT_GRAY8, MKTAG('G', 'R', 'E', 'Y') },
|
---|
52 |
|
---|
53 | /* quicktime */
|
---|
54 | { PIX_FMT_UYVY422, MKTAG('2', 'v', 'u', 'y') },
|
---|
55 |
|
---|
56 | { -1, 0 },
|
---|
57 | };
|
---|
58 |
|
---|
59 | static int findPixelFormat(unsigned int fourcc)
|
---|
60 | {
|
---|
61 | const PixelFormatTag * tags = pixelFormatTags;
|
---|
62 | while (tags->pix_fmt >= 0) {
|
---|
63 | if (tags->fourcc == fourcc)
|
---|
64 | return tags->pix_fmt;
|
---|
65 | tags++;
|
---|
66 | }
|
---|
67 | return PIX_FMT_YUV420P;
|
---|
68 | }
|
---|
69 |
|
---|
70 | unsigned int avcodec_pix_fmt_to_codec_tag(enum PixelFormat fmt)
|
---|
71 | {
|
---|
72 | const PixelFormatTag * tags = pixelFormatTags;
|
---|
73 | while (tags->pix_fmt >= 0) {
|
---|
74 | if (tags->pix_fmt == fmt)
|
---|
75 | return tags->fourcc;
|
---|
76 | tags++;
|
---|
77 | }
|
---|
78 | return 0;
|
---|
79 | }
|
---|
80 |
|
---|
81 | /* RAW Decoder Implementation */
|
---|
82 |
|
---|
83 | static int raw_init_decoder(AVCodecContext *avctx)
|
---|
84 | {
|
---|
85 | RawVideoContext *context = avctx->priv_data;
|
---|
86 |
|
---|
87 | if (avctx->codec_tag)
|
---|
88 | avctx->pix_fmt = findPixelFormat(avctx->codec_tag);
|
---|
89 | else if (avctx->bits_per_sample){
|
---|
90 | switch(avctx->bits_per_sample){
|
---|
91 | case 8: avctx->pix_fmt= PIX_FMT_PAL8 ; break;
|
---|
92 | case 15: avctx->pix_fmt= PIX_FMT_RGB555; break;
|
---|
93 | case 16: avctx->pix_fmt= PIX_FMT_RGB565; break;
|
---|
94 | case 24: avctx->pix_fmt= PIX_FMT_BGR24 ; break;
|
---|
95 | case 32: avctx->pix_fmt= PIX_FMT_RGBA32; break;
|
---|
96 | }
|
---|
97 | }
|
---|
98 |
|
---|
99 | context->length = avpicture_get_size(avctx->pix_fmt, avctx->width, avctx->height);
|
---|
100 | context->buffer = av_malloc(context->length);
|
---|
101 | context->pic.pict_type = FF_I_TYPE;
|
---|
102 | context->pic.key_frame = 1;
|
---|
103 |
|
---|
104 | avctx->coded_frame= &context->pic;
|
---|
105 |
|
---|
106 | if (!context->buffer)
|
---|
107 | return -1;
|
---|
108 |
|
---|
109 | return 0;
|
---|
110 | }
|
---|
111 |
|
---|
112 | static void flip(AVCodecContext *avctx, AVPicture * picture){
|
---|
113 | if(!avctx->codec_tag && avctx->bits_per_sample && picture->linesize[2]==0){
|
---|
114 | picture->data[0] += picture->linesize[0] * (avctx->height-1);
|
---|
115 | picture->linesize[0] *= -1;
|
---|
116 | }
|
---|
117 | }
|
---|
118 |
|
---|
119 | static int raw_decode(AVCodecContext *avctx,
|
---|
120 | void *data, int *data_size,
|
---|
121 | uint8_t *buf, int buf_size)
|
---|
122 | {
|
---|
123 | RawVideoContext *context = avctx->priv_data;
|
---|
124 |
|
---|
125 | AVFrame * frame = (AVFrame *) data;
|
---|
126 | AVPicture * picture = (AVPicture *) data;
|
---|
127 |
|
---|
128 | frame->interlaced_frame = avctx->coded_frame->interlaced_frame;
|
---|
129 | frame->top_field_first = avctx->coded_frame->top_field_first;
|
---|
130 |
|
---|
131 | if(buf_size < context->length - (avctx->pix_fmt==PIX_FMT_PAL8 ? 256*4 : 0))
|
---|
132 | return -1;
|
---|
133 |
|
---|
134 | avpicture_fill(picture, buf, avctx->pix_fmt, avctx->width, avctx->height);
|
---|
135 | if(avctx->pix_fmt==PIX_FMT_PAL8 && buf_size < context->length){
|
---|
136 | frame->data[1]= context->buffer;
|
---|
137 | }
|
---|
138 | if (avctx->palctrl && avctx->palctrl->palette_changed) {
|
---|
139 | memcpy(frame->data[1], avctx->palctrl->palette, AVPALETTE_SIZE);
|
---|
140 | avctx->palctrl->palette_changed = 0;
|
---|
141 | }
|
---|
142 |
|
---|
143 | flip(avctx, picture);
|
---|
144 | *data_size = sizeof(AVPicture);
|
---|
145 | return buf_size;
|
---|
146 | }
|
---|
147 |
|
---|
148 | static int raw_close_decoder(AVCodecContext *avctx)
|
---|
149 | {
|
---|
150 | RawVideoContext *context = avctx->priv_data;
|
---|
151 |
|
---|
152 | av_freep(&context->buffer);
|
---|
153 | return 0;
|
---|
154 | }
|
---|
155 |
|
---|
156 | /* RAW Encoder Implementation */
|
---|
157 |
|
---|
158 | static int raw_init_encoder(AVCodecContext *avctx)
|
---|
159 | {
|
---|
160 | avctx->coded_frame = (AVFrame *)avctx->priv_data;
|
---|
161 | avctx->coded_frame->pict_type = FF_I_TYPE;
|
---|
162 | avctx->coded_frame->key_frame = 1;
|
---|
163 | if(!avctx->codec_tag)
|
---|
164 | avctx->codec_tag = avcodec_pix_fmt_to_codec_tag(avctx->pix_fmt);
|
---|
165 | return 0;
|
---|
166 | }
|
---|
167 |
|
---|
168 | static int raw_encode(AVCodecContext *avctx,
|
---|
169 | unsigned char *frame, int buf_size, void *data)
|
---|
170 | {
|
---|
171 | return avpicture_layout((AVPicture *)data, avctx->pix_fmt, avctx->width,
|
---|
172 | avctx->height, frame, buf_size);
|
---|
173 | }
|
---|
174 |
|
---|
175 | #ifdef CONFIG_RAWVIDEO_ENCODER
|
---|
176 | AVCodec rawvideo_encoder = {
|
---|
177 | "rawvideo",
|
---|
178 | CODEC_TYPE_VIDEO,
|
---|
179 | CODEC_ID_RAWVIDEO,
|
---|
180 | sizeof(AVFrame),
|
---|
181 | raw_init_encoder,
|
---|
182 | raw_encode,
|
---|
183 | };
|
---|
184 | #endif // CONFIG_RAWVIDEO_ENCODER
|
---|
185 |
|
---|
186 | AVCodec rawvideo_decoder = {
|
---|
187 | "rawvideo",
|
---|
188 | CODEC_TYPE_VIDEO,
|
---|
189 | CODEC_ID_RAWVIDEO,
|
---|
190 | sizeof(RawVideoContext),
|
---|
191 | raw_init_decoder,
|
---|
192 | NULL,
|
---|
193 | raw_close_decoder,
|
---|
194 | raw_decode,
|
---|
195 | };
|
---|