~ubuntu-branches/ubuntu/jaunty/xvidcap/jaunty-proposed

« back to all changes in this revision

Viewing changes to ffmpeg/vhook/ppm.c

  • Committer: Bazaar Package Importer
  • Author(s): John Dong
  • Date: 2008-02-25 15:47:12 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20080225154712-qvr11ekcea4c9ry8
Tags: 1.1.6-0.1ubuntu1
* Merge from debian-multimedia (LP: #120003), Ubuntu Changes:
 - For ffmpeg-related build-deps, remove cvs from package names.
 - Standards-Version 3.7.3
 - Maintainer Spec

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
 
 * PPM Video Hook 
 
2
 * PPM Video Hook
3
3
 * Copyright (c) 2003 Charles Yates
4
4
 *
5
 
 * This library is free software; you can redistribute it and/or
 
5
 * This file is part of FFmpeg.
 
6
 *
 
7
 * FFmpeg is free software; you can redistribute it and/or
6
8
 * modify it under the terms of the GNU Lesser General Public
7
9
 * License as published by the Free Software Foundation; either
8
 
 * version 2 of the License, or (at your option) any later version.
 
10
 * version 2.1 of the License, or (at your option) any later version.
9
11
 *
10
 
 * This library is distributed in the hope that it will be useful,
 
12
 * FFmpeg is distributed in the hope that it will be useful,
11
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13
15
 * Lesser General Public License for more details.
14
16
 *
15
17
 * 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
 * License along with FFmpeg; if not, write to the Free Software
 
19
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18
20
 */
19
21
 
20
22
#include <stdio.h>
24
26
#include <sys/wait.h>
25
27
#include <ctype.h>
26
28
#include "framehook.h"
 
29
#include "avformat.h"
 
30
#include "swscale.h"
 
31
 
 
32
static int sws_flags = SWS_BICUBIC;
27
33
 
28
34
/** Bi-directional pipe structure.
29
35
*/
30
36
 
31
37
typedef struct rwpipe
32
38
{
33
 
        int pid;
34
 
        FILE *reader;
35
 
        FILE *writer;
 
39
    int pid;
 
40
    FILE *reader;
 
41
    FILE *writer;
36
42
}
37
43
rwpipe;
38
44
 
39
45
/** Create a bidirectional pipe for the given command.
40
46
*/
41
47
 
42
 
rwpipe *rwpipe_open( int argc, char *argv[] )
 
48
static rwpipe *rwpipe_open( int argc, char *argv[] )
43
49
{
44
 
        rwpipe *this = av_mallocz( sizeof( rwpipe ) );
 
50
    rwpipe *this = av_mallocz( sizeof( rwpipe ) );
45
51
 
46
 
        if ( this != NULL )
47
 
        {
 
52
    if ( this != NULL )
 
53
    {
48
54
        int input[ 2 ];
49
55
        int output[ 2 ];
50
56
 
55
61
 
56
62
        if ( this->pid == 0 )
57
63
        {
58
 
                        char *command = av_mallocz( 10240 );
59
 
                        int i;
 
64
#define COMMAND_SIZE 10240
 
65
            char *command = av_mallocz( COMMAND_SIZE );
 
66
            int i;
60
67
 
61
 
                        strcpy( command, "" );
62
 
                        for ( i = 0; i < argc; i ++ )
63
 
                        {
64
 
                                strcat( command, argv[ i ] );
65
 
                                strcat( command, " " );
66
 
                        }
 
68
            strcpy( command, "" );
 
69
            for ( i = 0; i < argc; i ++ )
 
70
            {
 
71
                pstrcat( command, COMMAND_SIZE, argv[ i ] );
 
72
                pstrcat( command, COMMAND_SIZE, " " );
 
73
            }
67
74
 
68
75
            dup2( output[ 0 ], STDIN_FILENO );
69
76
            dup2( input[ 1 ], STDOUT_FILENO );
73
80
            close( output[ 0 ] );
74
81
            close( output[ 1 ] );
75
82
 
76
 
            execl("/bin/sh", "sh", "-c", command, NULL );
77
 
                        exit( 255 );
 
83
            execl("/bin/sh", "sh", "-c", command, (char*)NULL );
 
84
            exit( 255 );
78
85
        }
79
86
        else
80
87
        {
84
91
            this->reader = fdopen( input[ 0 ], "r" );
85
92
            this->writer = fdopen( output[ 1 ], "w" );
86
93
        }
87
 
        }
 
94
    }
88
95
 
89
 
        return this;
 
96
    return this;
90
97
}
91
98
 
92
99
/** Read data from the pipe.
93
100
*/
94
101
 
95
 
FILE *rwpipe_reader( rwpipe *this )
 
102
static FILE *rwpipe_reader( rwpipe *this )
96
103
{
97
 
        if ( this != NULL )
98
 
                return this->reader;
99
 
        else
100
 
                return NULL;
 
104
    if ( this != NULL )
 
105
        return this->reader;
 
106
    else
 
107
        return NULL;
101
108
}
102
109
 
103
110
/** Write data to the pipe.
104
111
*/
105
112
 
106
 
FILE *rwpipe_writer( rwpipe *this )
107
 
{
108
 
        if ( this != NULL )
109
 
                return this->writer;
110
 
        else
111
 
                return NULL;
 
113
static FILE *rwpipe_writer( rwpipe *this )
 
114
{
 
115
    if ( this != NULL )
 
116
        return this->writer;
 
117
    else
 
118
        return NULL;
 
119
}
 
120
 
 
121
/* Read a number from the pipe - assumes PNM style headers.
 
122
*/
 
123
 
 
124
static int rwpipe_read_number( rwpipe *rw )
 
125
{
 
126
    int value = 0;
 
127
    int c = 0;
 
128
    FILE *in = rwpipe_reader( rw );
 
129
 
 
130
    do
 
131
    {
 
132
        c = fgetc( in );
 
133
 
 
134
        while( c != EOF && !isdigit( c ) && c != '#' )
 
135
            c = fgetc( in );
 
136
 
 
137
        if ( c == '#' )
 
138
            while( c != EOF && c != '\n' )
 
139
                c = fgetc( in );
 
140
    }
 
141
    while ( c != EOF && !isdigit( c ) );
 
142
 
 
143
    while( c != EOF && isdigit( c ) )
 
144
    {
 
145
        value = value * 10 + ( c - '0' );
 
146
        c = fgetc( in );
 
147
    }
 
148
 
 
149
    return value;
 
150
}
 
151
 
 
152
/** Read a PPM P6 header.
 
153
*/
 
154
 
 
155
static int rwpipe_read_ppm_header( rwpipe *rw, int *width, int *height )
 
156
{
 
157
    char line[ 3 ];
 
158
    FILE *in = rwpipe_reader( rw );
 
159
    int max;
 
160
 
 
161
    fgets( line, 3, in );
 
162
    if ( !strncmp( line, "P6", 2 ) )
 
163
    {
 
164
        *width = rwpipe_read_number( rw );
 
165
        *height = rwpipe_read_number( rw );
 
166
        max = rwpipe_read_number( rw );
 
167
        return max != 255 || *width <= 0 || *height <= 0;
 
168
    }
 
169
    return 1;
112
170
}
113
171
 
114
172
/** Close the pipe and process.
115
173
*/
116
174
 
117
 
void rwpipe_close( rwpipe *this )
118
 
{
119
 
        if ( this != NULL )
120
 
        {
121
 
                fclose( this->reader );
122
 
                fclose( this->writer );
123
 
                waitpid( this->pid, NULL, 0 );
124
 
                av_free( this );
125
 
        }
126
 
}
127
 
 
128
 
typedef struct 
129
 
{
130
 
        rwpipe *rw;
131
 
 
175
static void rwpipe_close( rwpipe *this )
 
176
{
 
177
    if ( this != NULL )
 
178
    {
 
179
        fclose( this->reader );
 
180
        fclose( this->writer );
 
181
        waitpid( this->pid, NULL, 0 );
 
182
        av_free( this );
 
183
    }
 
184
}
 
185
 
 
186
/** Context info for this vhook - stores the pipe and image buffers.
 
187
*/
 
188
 
 
189
typedef struct
 
190
{
 
191
    rwpipe *rw;
 
192
    int size1;
 
193
    char *buf1;
 
194
    int size2;
 
195
    char *buf2;
 
196
 
 
197
    // This vhook first converts frame to RGB ...
 
198
    struct SwsContext *toRGB_convert_ctx;
 
199
    // ... then processes it via a PPM command pipe ...
 
200
    // ... and finally converts back frame from RGB to initial format
 
201
    struct SwsContext *fromRGB_convert_ctx;
 
202
}
132
203
ContextInfo;
133
204
 
 
205
/** Initialise the context info for this vhook.
 
206
*/
 
207
 
134
208
int Configure(void **ctxp, int argc, char *argv[])
135
209
{
136
 
    *ctxp = av_mallocz(sizeof(ContextInfo));
137
 
        if ( ctxp != NULL && argc > 1 )
138
 
        {
139
 
                ContextInfo *info = (ContextInfo *)*ctxp;
140
 
                info->rw = rwpipe_open( argc - 1, &argv[ 1 ] );
141
 
        }
142
 
    return 0;
143
 
}
144
 
 
145
 
int rwpipe_read_number( rwpipe *rw )
146
 
{
147
 
        int value = 0;
148
 
        int c = 0;
149
 
        FILE *in = rwpipe_reader( rw );
150
 
 
151
 
        do 
152
 
        {
153
 
                c = fgetc( in );
154
 
 
155
 
                while( c != EOF && !isdigit( c ) && c != '#' )
156
 
                        c = fgetc( in );
157
 
 
158
 
                if ( c == '#' )
159
 
                        while( c != EOF && c != '\n' )
160
 
                                c = fgetc( in );
161
 
        }
162
 
        while ( c != EOF && !isdigit( c ) );
163
 
 
164
 
        while( c != EOF && isdigit( c ) )
165
 
        {
166
 
                value = value * 10 + ( c - '0' );
167
 
                c = fgetc( in );
168
 
        }
169
 
 
170
 
        return value;
171
 
}
172
 
 
173
 
int rwpipe_read_ppm_header( rwpipe *rw, int *width, int *height )
174
 
{
175
 
        char line[ 3 ];
176
 
        FILE *in = rwpipe_reader( rw );
177
 
        int max;
178
 
 
179
 
        fgets( line, 3, in );
180
 
        if ( !strncmp( line, "P6", 2 ) )
181
 
        {
182
 
                *width = rwpipe_read_number( rw );
183
 
                *height = rwpipe_read_number( rw );
184
 
                max = rwpipe_read_number( rw );
185
 
                return max != 255 || *width <= 0 || *height <= 0;
186
 
        }
187
 
        return 1;
188
 
}
 
210
    if ( argc > 1 )
 
211
    {
 
212
        *ctxp = av_mallocz(sizeof(ContextInfo));
 
213
        if ( ctxp != NULL && argc > 1 )
 
214
        {
 
215
            ContextInfo *info = (ContextInfo *)*ctxp;
 
216
            info->rw = rwpipe_open( argc - 1, &argv[ 1 ] );
 
217
            return 0;
 
218
        }
 
219
    }
 
220
    return 1;
 
221
}
 
222
 
 
223
/** Process a frame.
 
224
*/
189
225
 
190
226
void Process(void *ctx, AVPicture *picture, enum PixelFormat pix_fmt, int width, int height, int64_t pts)
191
227
{
192
 
        int err = 0;
 
228
    int err = 0;
193
229
    ContextInfo *ci = (ContextInfo *) ctx;
194
 
    char *buf1 = 0;
195
 
    char *buf2 = 0;
196
230
    AVPicture picture1;
197
231
    AVPicture picture2;
198
232
    AVPicture *pict = picture;
199
 
        int out_width;
200
 
        int out_height;
201
 
        int i;
202
 
        uint8_t *ptr = NULL;
203
 
        FILE *in = rwpipe_reader( ci->rw );
204
 
        FILE *out = rwpipe_writer( ci->rw );
205
 
 
206
 
        /* Convert to RGB24 if necessary */
207
 
    if (pix_fmt != PIX_FMT_RGB24) {
208
 
        int size;
209
 
 
210
 
        size = avpicture_get_size(PIX_FMT_RGB24, width, height);
211
 
        buf1 = av_malloc(size);
212
 
 
213
 
        avpicture_fill(&picture1, buf1, PIX_FMT_RGB24, width, height);
214
 
        if (img_convert(&picture1, PIX_FMT_RGB24, 
215
 
                        picture, pix_fmt, width, height) < 0) {
216
 
                        err = 1;
217
 
        }
218
 
        pict = &picture1;
219
 
    }
220
 
 
221
 
        /* Write out the PPM */
222
 
        if ( !err )
223
 
        {
224
 
                ptr = pict->data[ 0 ];
225
 
                fprintf( out, "P6\n%d %d\n255\n", width, height );
226
 
                for ( i = 0; !err && i < height; i ++ )
227
 
                {
228
 
                        err = !fwrite( ptr, width * 3, 1, out );
229
 
                        ptr += pict->linesize[ 0 ];
230
 
                }
231
 
                if ( !err )
232
 
                        err = fflush( out );
233
 
        }
234
 
 
235
 
        /* Read the PPM returned. */
236
 
        if ( !err && !rwpipe_read_ppm_header( ci->rw, &out_width, &out_height ) )
237
 
        {
 
233
    int out_width;
 
234
    int out_height;
 
235
    int i;
 
236
    uint8_t *ptr = NULL;
 
237
    FILE *in = rwpipe_reader( ci->rw );
 
238
    FILE *out = rwpipe_writer( ci->rw );
 
239
 
 
240
    /* Check that we have a pipe to talk to. */
 
241
    if ( in == NULL || out == NULL )
 
242
        err = 1;
 
243
 
 
244
    /* Convert to RGB24 if necessary */
 
245
    if ( !err && pix_fmt != PIX_FMT_RGB24 )
 
246
    {
 
247
        int size = avpicture_get_size(PIX_FMT_RGB24, width, height);
 
248
 
 
249
        if ( size != ci->size1 )
 
250
        {
 
251
            av_free( ci->buf1 );
 
252
            ci->buf1 = av_malloc(size);
 
253
            ci->size1 = size;
 
254
            err = ci->buf1 == NULL;
 
255
        }
 
256
 
 
257
        if ( !err )
 
258
        {
 
259
            avpicture_fill(&picture1, ci->buf1, PIX_FMT_RGB24, width, height);
 
260
 
 
261
            // if we already got a SWS context, let's realloc if is not re-useable
 
262
            ci->toRGB_convert_ctx = sws_getCachedContext(ci->toRGB_convert_ctx,
 
263
                                        width, height, pix_fmt,
 
264
                                        width, height, PIX_FMT_RGB24,
 
265
                                        sws_flags, NULL, NULL, NULL);
 
266
            if (ci->toRGB_convert_ctx == NULL) {
 
267
                av_log(NULL, AV_LOG_ERROR,
 
268
                       "Cannot initialize the toRGB conversion context\n");
 
269
                exit(1);
 
270
            }
 
271
 
 
272
// img_convert parameters are          2 first destination, then 4 source
 
273
// sws_scale   parameters are context, 4 first source,      then 2 destination
 
274
            sws_scale(ci->toRGB_convert_ctx,
 
275
                     picture->data, picture->linesize, 0, height,
 
276
                     picture1.data, picture1.linesize);
 
277
 
 
278
            pict = &picture1;
 
279
        }
 
280
    }
 
281
 
 
282
    /* Write out the PPM */
 
283
    if ( !err )
 
284
    {
 
285
        ptr = pict->data[ 0 ];
 
286
        fprintf( out, "P6\n%d %d\n255\n", width, height );
 
287
        for ( i = 0; !err && i < height; i ++ )
 
288
        {
 
289
            err = !fwrite( ptr, width * 3, 1, out );
 
290
            ptr += pict->linesize[ 0 ];
 
291
        }
 
292
        if ( !err )
 
293
            err = fflush( out );
 
294
    }
 
295
 
 
296
    /* Read the PPM returned. */
 
297
    if ( !err && !rwpipe_read_ppm_header( ci->rw, &out_width, &out_height ) )
 
298
    {
238
299
        int size = avpicture_get_size(PIX_FMT_RGB24, out_width, out_height);
239
 
        buf2 = av_malloc(size);
240
 
        avpicture_fill(&picture2, buf2, PIX_FMT_RGB24, out_width, out_height);
241
 
                ptr = picture2.data[ 0 ];
242
 
                for ( i = 0; !err && i < out_height; i ++ )
243
 
                {
244
 
                        err = !fread( ptr, out_width * 3, 1, in );
245
 
                        ptr += picture2.linesize[ 0 ];
246
 
                }
247
 
        }
248
 
 
249
 
        /* Convert the returned PPM back to the input format */
250
 
        if ( !err )
251
 
        {
252
 
        if (img_convert(picture, pix_fmt, &picture2, PIX_FMT_RGB24, width, height) < 0) {
253
 
        }
254
 
        }
255
 
 
256
 
    av_free(buf1);
257
 
    av_free(buf2);
 
300
 
 
301
        if ( size != ci->size2 )
 
302
        {
 
303
            av_free( ci->buf2 );
 
304
            ci->buf2 = av_malloc(size);
 
305
            ci->size2 = size;
 
306
            err = ci->buf2 == NULL;
 
307
        }
 
308
 
 
309
        if ( !err )
 
310
        {
 
311
            avpicture_fill(&picture2, ci->buf2, PIX_FMT_RGB24, out_width, out_height);
 
312
            ptr = picture2.data[ 0 ];
 
313
            for ( i = 0; !err && i < out_height; i ++ )
 
314
            {
 
315
                err = !fread( ptr, out_width * 3, 1, in );
 
316
                ptr += picture2.linesize[ 0 ];
 
317
            }
 
318
        }
 
319
    }
 
320
 
 
321
    /* Convert the returned PPM back to the input format */
 
322
    if ( !err )
 
323
    {
 
324
        /* The out_width/out_height returned from the PPM
 
325
         * filter won't necessarily be the same as width and height
 
326
         * but it will be scaled anyway to width/height.
 
327
         */
 
328
        av_log(NULL, AV_LOG_DEBUG,
 
329
                  "PPM vhook: Input dimensions: %d x %d Output dimensions: %d x %d\n",
 
330
                  width, height, out_width, out_height);
 
331
        ci->fromRGB_convert_ctx = sws_getCachedContext(ci->fromRGB_convert_ctx,
 
332
                                        out_width, out_height, PIX_FMT_RGB24,
 
333
                                        width,     height,     pix_fmt,
 
334
                                        sws_flags, NULL, NULL, NULL);
 
335
        if (ci->fromRGB_convert_ctx == NULL) {
 
336
            av_log(NULL, AV_LOG_ERROR,
 
337
                   "Cannot initialize the fromRGB conversion context\n");
 
338
            exit(1);
 
339
        }
 
340
 
 
341
// img_convert parameters are          2 first destination, then 4 source
 
342
// sws_scale   parameters are context, 4 first source,      then 2 destination
 
343
        sws_scale(ci->fromRGB_convert_ctx,
 
344
                 picture2.data, picture2.linesize, 0, out_height,
 
345
                 picture->data, picture->linesize);
 
346
    }
258
347
}
259
348
 
 
349
/** Clean up the effect.
 
350
*/
 
351
 
260
352
void Release(void *ctx)
261
353
{
262
354
    ContextInfo *ci;
263
355
    ci = (ContextInfo *) ctx;
264
356
 
265
357
    if (ctx)
266
 
        {
267
 
                rwpipe_close( ci->rw );
 
358
    {
 
359
        rwpipe_close( ci->rw );
 
360
        av_free( ci->buf1 );
 
361
        av_free( ci->buf2 );
 
362
        sws_freeContext(ci->toRGB_convert_ctx);
 
363
        sws_freeContext(ci->fromRGB_convert_ctx);
268
364
        av_free(ctx);
269
 
        }
 
365
    }
270
366
}
271
367