Statistics
| Branch: | Revision:

ffmpeg / libavcodec / pnmenc.c @ 9ac2e797

History | View | Annotate | Download (11.3 KB)

1
/*
2
 * PNM image format
3
 * Copyright (c) 2002, 2003 Fabrice Bellard.
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
#include "avcodec.h"
22
#include "pnm.h"
23

    
24

    
25
static int common_init(AVCodecContext *avctx){
26
    PNMContext *s = avctx->priv_data;
27

    
28
    avcodec_get_frame_defaults((AVFrame*)&s->picture);
29
    avctx->coded_frame= (AVFrame*)&s->picture;
30

    
31
    return 0;
32
}
33

    
34
static int pnm_decode_frame(AVCodecContext *avctx,
35
                        void *data, int *data_size,
36
                        uint8_t *buf, int buf_size)
37
{
38
    PNMContext * const s = avctx->priv_data;
39
    AVFrame *picture = data;
40
    AVFrame * const p= (AVFrame*)&s->picture;
41
    int i, n, linesize, h, upgrade = 0;
42
    unsigned char *ptr;
43

    
44
    s->bytestream_start=
45
    s->bytestream= buf;
46
    s->bytestream_end= buf + buf_size;
47

    
48
    if(ff_pnm_decode_header(avctx, s) < 0)
49
        return -1;
50

    
51
    if(p->data[0])
52
        avctx->release_buffer(avctx, p);
53

    
54
    p->reference= 0;
55
    if(avctx->get_buffer(avctx, p) < 0){
56
        av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
57
        return -1;
58
    }
59
    p->pict_type= FF_I_TYPE;
60
    p->key_frame= 1;
61

    
62
    switch(avctx->pix_fmt) {
63
    default:
64
        return -1;
65
    case PIX_FMT_RGB24:
66
        n = avctx->width * 3;
67
        goto do_read;
68
    case PIX_FMT_GRAY8:
69
        n = avctx->width;
70
        if (s->maxval < 255)
71
            upgrade = 1;
72
        goto do_read;
73
    case PIX_FMT_GRAY16BE:
74
    case PIX_FMT_GRAY16LE:
75
        n = avctx->width * 2;
76
        if (s->maxval < 65535)
77
            upgrade = 2;
78
        goto do_read;
79
    case PIX_FMT_MONOWHITE:
80
    case PIX_FMT_MONOBLACK:
81
        n = (avctx->width + 7) >> 3;
82
    do_read:
83
        ptr = p->data[0];
84
        linesize = p->linesize[0];
85
        if(s->bytestream + n*avctx->height > s->bytestream_end)
86
            return -1;
87
        for(i = 0; i < avctx->height; i++) {
88
            if (!upgrade)
89
                memcpy(ptr, s->bytestream, n);
90
            else if (upgrade == 1) {
91
                unsigned int j, f = (255*128 + s->maxval/2) / s->maxval;
92
                for (j=0; j<n; j++)
93
                    ptr[j] = (s->bytestream[j] * f + 64) >> 7;
94
            } else if (upgrade == 2) {
95
                unsigned int j, v, f = (65535*32768 + s->maxval/2) / s->maxval;
96
                for (j=0; j<n/2; j++) {
97
                    v = be2me_16(((uint16_t *)s->bytestream)[j]);
98
                    ((uint16_t *)ptr)[j] = (v * f + 16384) >> 15;
99
                }
100
            }
101
            s->bytestream += n;
102
            ptr += linesize;
103
        }
104
        break;
105
    case PIX_FMT_YUV420P:
106
        {
107
            unsigned char *ptr1, *ptr2;
108

    
109
            n = avctx->width;
110
            ptr = p->data[0];
111
            linesize = p->linesize[0];
112
            if(s->bytestream + n*avctx->height*3/2 > s->bytestream_end)
113
                return -1;
114
            for(i = 0; i < avctx->height; i++) {
115
                memcpy(ptr, s->bytestream, n);
116
                s->bytestream += n;
117
                ptr += linesize;
118
            }
119
            ptr1 = p->data[1];
120
            ptr2 = p->data[2];
121
            n >>= 1;
122
            h = avctx->height >> 1;
123
            for(i = 0; i < h; i++) {
124
                memcpy(ptr1, s->bytestream, n);
125
                s->bytestream += n;
126
                memcpy(ptr2, s->bytestream, n);
127
                s->bytestream += n;
128
                ptr1 += p->linesize[1];
129
                ptr2 += p->linesize[2];
130
            }
131
        }
132
        break;
133
    case PIX_FMT_RGB32:
134
        ptr = p->data[0];
135
        linesize = p->linesize[0];
136
        if(s->bytestream + avctx->width*avctx->height*4 > s->bytestream_end)
137
            return -1;
138
        for(i = 0; i < avctx->height; i++) {
139
            int j, r, g, b, a;
140

    
141
            for(j = 0;j < avctx->width; j++) {
142
                r = *s->bytestream++;
143
                g = *s->bytestream++;
144
                b = *s->bytestream++;
145
                a = *s->bytestream++;
146
                ((uint32_t *)ptr)[j] = (a << 24) | (r << 16) | (g << 8) | b;
147
            }
148
            ptr += linesize;
149
        }
150
        break;
151
    }
152
    *picture= *(AVFrame*)&s->picture;
153
    *data_size = sizeof(AVPicture);
154

    
155
    return s->bytestream - s->bytestream_start;
156
}
157

    
158
static int pnm_encode_frame(AVCodecContext *avctx, unsigned char *outbuf, int buf_size, void *data){
159
    PNMContext *s = avctx->priv_data;
160
    AVFrame *pict = data;
161
    AVFrame * const p= (AVFrame*)&s->picture;
162
    int i, h, h1, c, n, linesize;
163
    uint8_t *ptr, *ptr1, *ptr2;
164

    
165
    if(buf_size < avpicture_get_size(avctx->pix_fmt, avctx->width, avctx->height) + 200){
166
        av_log(avctx, AV_LOG_ERROR, "encoded frame too large\n");
167
        return -1;
168
    }
169

    
170
    *p = *pict;
171
    p->pict_type= FF_I_TYPE;
172
    p->key_frame= 1;
173

    
174
    s->bytestream_start=
175
    s->bytestream= outbuf;
176
    s->bytestream_end= outbuf+buf_size;
177

    
178
    h = avctx->height;
179
    h1 = h;
180
    switch(avctx->pix_fmt) {
181
    case PIX_FMT_MONOWHITE:
182
        c = '4';
183
        n = (avctx->width + 7) >> 3;
184
        break;
185
    case PIX_FMT_GRAY8:
186
        c = '5';
187
        n = avctx->width;
188
        break;
189
    case PIX_FMT_GRAY16BE:
190
        c = '5';
191
        n = avctx->width * 2;
192
        break;
193
    case PIX_FMT_RGB24:
194
        c = '6';
195
        n = avctx->width * 3;
196
        break;
197
    case PIX_FMT_YUV420P:
198
        c = '5';
199
        n = avctx->width;
200
        h1 = (h * 3) / 2;
201
        break;
202
    default:
203
        return -1;
204
    }
205
    snprintf(s->bytestream, s->bytestream_end - s->bytestream,
206
             "P%c\n%d %d\n",
207
             c, avctx->width, h1);
208
    s->bytestream += strlen(s->bytestream);
209
    if (avctx->pix_fmt != PIX_FMT_MONOWHITE) {
210
        snprintf(s->bytestream, s->bytestream_end - s->bytestream,
211
                 "%d\n", (avctx->pix_fmt != PIX_FMT_GRAY16BE) ? 255 : 65535);
212
        s->bytestream += strlen(s->bytestream);
213
    }
214

    
215
    ptr = p->data[0];
216
    linesize = p->linesize[0];
217
    for(i=0;i<h;i++) {
218
        memcpy(s->bytestream, ptr, n);
219
        s->bytestream += n;
220
        ptr += linesize;
221
    }
222

    
223
    if (avctx->pix_fmt == PIX_FMT_YUV420P) {
224
        h >>= 1;
225
        n >>= 1;
226
        ptr1 = p->data[1];
227
        ptr2 = p->data[2];
228
        for(i=0;i<h;i++) {
229
            memcpy(s->bytestream, ptr1, n);
230
            s->bytestream += n;
231
            memcpy(s->bytestream, ptr2, n);
232
            s->bytestream += n;
233
                ptr1 += p->linesize[1];
234
                ptr2 += p->linesize[2];
235
        }
236
    }
237
    return s->bytestream - s->bytestream_start;
238
}
239

    
240
static int pam_encode_frame(AVCodecContext *avctx, unsigned char *outbuf, int buf_size, void *data){
241
    PNMContext *s = avctx->priv_data;
242
    AVFrame *pict = data;
243
    AVFrame * const p= (AVFrame*)&s->picture;
244
    int i, h, w, n, linesize, depth, maxval;
245
    const char *tuple_type;
246
    uint8_t *ptr;
247

    
248
    if(buf_size < avpicture_get_size(avctx->pix_fmt, avctx->width, avctx->height) + 200){
249
        av_log(avctx, AV_LOG_ERROR, "encoded frame too large\n");
250
        return -1;
251
    }
252

    
253
    *p = *pict;
254
    p->pict_type= FF_I_TYPE;
255
    p->key_frame= 1;
256

    
257
    s->bytestream_start=
258
    s->bytestream= outbuf;
259
    s->bytestream_end= outbuf+buf_size;
260

    
261
    h = avctx->height;
262
    w = avctx->width;
263
    switch(avctx->pix_fmt) {
264
    case PIX_FMT_MONOWHITE:
265
        n = (w + 7) >> 3;
266
        depth = 1;
267
        maxval = 1;
268
        tuple_type = "BLACKANDWHITE";
269
        break;
270
    case PIX_FMT_GRAY8:
271
        n = w;
272
        depth = 1;
273
        maxval = 255;
274
        tuple_type = "GRAYSCALE";
275
        break;
276
    case PIX_FMT_RGB24:
277
        n = w * 3;
278
        depth = 3;
279
        maxval = 255;
280
        tuple_type = "RGB";
281
        break;
282
    case PIX_FMT_RGB32:
283
        n = w * 4;
284
        depth = 4;
285
        maxval = 255;
286
        tuple_type = "RGB_ALPHA";
287
        break;
288
    default:
289
        return -1;
290
    }
291
    snprintf(s->bytestream, s->bytestream_end - s->bytestream,
292
             "P7\nWIDTH %d\nHEIGHT %d\nDEPTH %d\nMAXVAL %d\nTUPLETYPE %s\nENDHDR\n",
293
             w, h, depth, maxval, tuple_type);
294
    s->bytestream += strlen(s->bytestream);
295

    
296
    ptr = p->data[0];
297
    linesize = p->linesize[0];
298

    
299
    if (avctx->pix_fmt == PIX_FMT_RGB32) {
300
        int j;
301
        unsigned int v;
302

    
303
        for(i=0;i<h;i++) {
304
            for(j=0;j<w;j++) {
305
                v = ((uint32_t *)ptr)[j];
306
                *s->bytestream++ = v >> 16;
307
                *s->bytestream++ = v >> 8;
308
                *s->bytestream++ = v;
309
                *s->bytestream++ = v >> 24;
310
            }
311
            ptr += linesize;
312
        }
313
    } else {
314
        for(i=0;i<h;i++) {
315
            memcpy(s->bytestream, ptr, n);
316
            s->bytestream += n;
317
            ptr += linesize;
318
        }
319
    }
320
    return s->bytestream - s->bytestream_start;
321
}
322

    
323
#if 0
324
static int pnm_probe(AVProbeData *pd)
325
{
326
    const char *p = pd->buf;
327
    if (pd->buf_size >= 8 &&
328
        p[0] == 'P' &&
329
        p[1] >= '4' && p[1] <= '6' &&
330
        pnm_space(p[2]) )
331
        return AVPROBE_SCORE_MAX - 1; /* to permit pgmyuv probe */
332
    else
333
        return 0;
334
}
335

336
static int pgmyuv_probe(AVProbeData *pd)
337
{
338
    if (match_ext(pd->filename, "pgmyuv"))
339
        return AVPROBE_SCORE_MAX;
340
    else
341
        return 0;
342
}
343

344
static int pam_probe(AVProbeData *pd)
345
{
346
    const char *p = pd->buf;
347
    if (pd->buf_size >= 8 &&
348
        p[0] == 'P' &&
349
        p[1] == '7' &&
350
        p[2] == '\n')
351
        return AVPROBE_SCORE_MAX;
352
    else
353
        return 0;
354
}
355
#endif
356

    
357

    
358
#ifdef CONFIG_PGM_ENCODER
359
AVCodec pgm_encoder = {
360
    "pgm",
361
    CODEC_TYPE_VIDEO,
362
    CODEC_ID_PGM,
363
    sizeof(PNMContext),
364
    common_init,
365
    pnm_encode_frame,
366
    NULL, //encode_end,
367
    pnm_decode_frame,
368
    .pix_fmts= (enum PixelFormat[]){PIX_FMT_GRAY8, PIX_FMT_GRAY16BE, -1},
369
};
370
#endif // CONFIG_PGM_ENCODER
371

    
372
#ifdef CONFIG_PGMYUV_ENCODER
373
AVCodec pgmyuv_encoder = {
374
    "pgmyuv",
375
    CODEC_TYPE_VIDEO,
376
    CODEC_ID_PGMYUV,
377
    sizeof(PNMContext),
378
    common_init,
379
    pnm_encode_frame,
380
    NULL, //encode_end,
381
    pnm_decode_frame,
382
    .pix_fmts= (enum PixelFormat[]){PIX_FMT_YUV420P, -1},
383
};
384
#endif // CONFIG_PGMYUV_ENCODER
385

    
386
#ifdef CONFIG_PPM_ENCODER
387
AVCodec ppm_encoder = {
388
    "ppm",
389
    CODEC_TYPE_VIDEO,
390
    CODEC_ID_PPM,
391
    sizeof(PNMContext),
392
    common_init,
393
    pnm_encode_frame,
394
    NULL, //encode_end,
395
    pnm_decode_frame,
396
    .pix_fmts= (enum PixelFormat[]){PIX_FMT_RGB24, -1},
397
};
398
#endif // CONFIG_PPM_ENCODER
399

    
400
#ifdef CONFIG_PBM_ENCODER
401
AVCodec pbm_encoder = {
402
    "pbm",
403
    CODEC_TYPE_VIDEO,
404
    CODEC_ID_PBM,
405
    sizeof(PNMContext),
406
    common_init,
407
    pnm_encode_frame,
408
    NULL, //encode_end,
409
    pnm_decode_frame,
410
    .pix_fmts= (enum PixelFormat[]){PIX_FMT_MONOWHITE, -1},
411
};
412
#endif // CONFIG_PBM_ENCODER
413

    
414
#ifdef CONFIG_PAM_ENCODER
415
AVCodec pam_encoder = {
416
    "pam",
417
    CODEC_TYPE_VIDEO,
418
    CODEC_ID_PAM,
419
    sizeof(PNMContext),
420
    common_init,
421
    pam_encode_frame,
422
    NULL, //encode_end,
423
    pnm_decode_frame,
424
    .pix_fmts= (enum PixelFormat[]){PIX_FMT_RGB24, PIX_FMT_RGB32, PIX_FMT_GRAY8, PIX_FMT_MONOWHITE, -1},
425
};
426
#endif // CONFIG_PAM_ENCODER