Statistics
| Branch: | Revision:

ffmpeg / vhook / ppm.c @ 5509bffa

History | View | Annotate | Download (7.87 KB)

1 bee0d9e5 Charles Yates
/*
2 115329f1 Diego Biurrun
 * PPM Video Hook
3 bee0d9e5 Charles Yates
 * Copyright (c) 2003 Charles Yates
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 5509bffa Diego Biurrun
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 bee0d9e5 Charles Yates
 */
19
20
#include <stdio.h>
21
#include <unistd.h>
22
#include <fcntl.h>
23
#include <sys/types.h>
24
#include <sys/wait.h>
25
#include <ctype.h>
26
#include "framehook.h"
27 cf344ec7 Fran├žois Revol
#include "avformat.h"
28 bee0d9e5 Charles Yates
29
/** Bi-directional pipe structure.
30
*/
31
32
typedef struct rwpipe
33
{
34 1e4ddde2 Charles Yates
    int pid;
35
    FILE *reader;
36
    FILE *writer;
37 bee0d9e5 Charles Yates
}
38
rwpipe;
39
40
/** Create a bidirectional pipe for the given command.
41
*/
42
43
rwpipe *rwpipe_open( int argc, char *argv[] )
44
{
45 1e4ddde2 Charles Yates
    rwpipe *this = av_mallocz( sizeof( rwpipe ) );
46 bee0d9e5 Charles Yates
47 1e4ddde2 Charles Yates
    if ( this != NULL )
48
    {
49 bee0d9e5 Charles Yates
        int input[ 2 ];
50
        int output[ 2 ];
51
52
        pipe( input );
53
        pipe( output );
54
55
        this->pid = fork();
56
57
        if ( this->pid == 0 )
58
        {
59 1f3f9507 Michael Niedermayer
#define COMMAND_SIZE 10240
60
            char *command = av_mallocz( COMMAND_SIZE );
61 1e4ddde2 Charles Yates
            int i;
62 bee0d9e5 Charles Yates
63 1e4ddde2 Charles Yates
            strcpy( command, "" );
64
            for ( i = 0; i < argc; i ++ )
65
            {
66 1f3f9507 Michael Niedermayer
                pstrcat( command, COMMAND_SIZE, argv[ i ] );
67
                pstrcat( command, COMMAND_SIZE, " " );
68 1e4ddde2 Charles Yates
            }
69 bee0d9e5 Charles Yates
70
            dup2( output[ 0 ], STDIN_FILENO );
71
            dup2( input[ 1 ], STDOUT_FILENO );
72
73
            close( input[ 0 ] );
74
            close( input[ 1 ] );
75
            close( output[ 0 ] );
76
            close( output[ 1 ] );
77
78 efe41983 Michael Niedermayer
            execl("/bin/sh", "sh", "-c", command, (char*)NULL );
79 1e4ddde2 Charles Yates
            exit( 255 );
80 bee0d9e5 Charles Yates
        }
81
        else
82
        {
83
            close( input[ 1 ] );
84
            close( output[ 0 ] );
85
86
            this->reader = fdopen( input[ 0 ], "r" );
87
            this->writer = fdopen( output[ 1 ], "w" );
88
        }
89 1e4ddde2 Charles Yates
    }
90 bee0d9e5 Charles Yates
91 1e4ddde2 Charles Yates
    return this;
92 bee0d9e5 Charles Yates
}
93
94
/** Read data from the pipe.
95
*/
96
97
FILE *rwpipe_reader( rwpipe *this )
98
{
99 1e4ddde2 Charles Yates
    if ( this != NULL )
100
        return this->reader;
101
    else
102
        return NULL;
103 bee0d9e5 Charles Yates
}
104
105
/** Write data to the pipe.
106
*/
107
108
FILE *rwpipe_writer( rwpipe *this )
109
{
110 1e4ddde2 Charles Yates
    if ( this != NULL )
111
        return this->writer;
112
    else
113
        return NULL;
114
}
115
116
/* Read a number from the pipe - assumes PNM style headers.
117
*/
118
119
int rwpipe_read_number( rwpipe *rw )
120
{
121
    int value = 0;
122
    int c = 0;
123
    FILE *in = rwpipe_reader( rw );
124
125 115329f1 Diego Biurrun
    do
126 1e4ddde2 Charles Yates
    {
127
        c = fgetc( in );
128
129
        while( c != EOF && !isdigit( c ) && c != '#' )
130
            c = fgetc( in );
131
132
        if ( c == '#' )
133
            while( c != EOF && c != '\n' )
134
                c = fgetc( in );
135
    }
136
    while ( c != EOF && !isdigit( c ) );
137
138
    while( c != EOF && isdigit( c ) )
139
    {
140
        value = value * 10 + ( c - '0' );
141
        c = fgetc( in );
142
    }
143
144
    return value;
145
}
146
147
/** Read a PPM P6 header.
148
*/
149
150
int rwpipe_read_ppm_header( rwpipe *rw, int *width, int *height )
151
{
152
    char line[ 3 ];
153
    FILE *in = rwpipe_reader( rw );
154
    int max;
155
156
    fgets( line, 3, in );
157
    if ( !strncmp( line, "P6", 2 ) )
158
    {
159
        *width = rwpipe_read_number( rw );
160
        *height = rwpipe_read_number( rw );
161
        max = rwpipe_read_number( rw );
162
        return max != 255 || *width <= 0 || *height <= 0;
163
    }
164
    return 1;
165 bee0d9e5 Charles Yates
}
166
167
/** Close the pipe and process.
168
*/
169
170
void rwpipe_close( rwpipe *this )
171
{
172 1e4ddde2 Charles Yates
    if ( this != NULL )
173
    {
174
        fclose( this->reader );
175
        fclose( this->writer );
176
        waitpid( this->pid, NULL, 0 );
177
        av_free( this );
178
    }
179 bee0d9e5 Charles Yates
}
180
181 1e4ddde2 Charles Yates
/** Context info for this vhook - stores the pipe and image buffers.
182
*/
183
184 115329f1 Diego Biurrun
typedef struct
185 bee0d9e5 Charles Yates
{
186 1e4ddde2 Charles Yates
    rwpipe *rw;
187
    int size1;
188
    char *buf1;
189
    int size2;
190
    char *buf2;
191 115329f1 Diego Biurrun
}
192 bee0d9e5 Charles Yates
ContextInfo;
193
194 1e4ddde2 Charles Yates
/** Initialise the context info for this vhook.
195
*/
196 bee0d9e5 Charles Yates
197 1e4ddde2 Charles Yates
int Configure(void **ctxp, int argc, char *argv[])
198 bee0d9e5 Charles Yates
{
199 1e4ddde2 Charles Yates
    if ( argc > 1 )
200
    {
201
        *ctxp = av_mallocz(sizeof(ContextInfo));
202
        if ( ctxp != NULL && argc > 1 )
203
        {
204
            ContextInfo *info = (ContextInfo *)*ctxp;
205
            info->rw = rwpipe_open( argc - 1, &argv[ 1 ] );
206
            return 0;
207
        }
208
    }
209
    return 1;
210 bee0d9e5 Charles Yates
}
211
212 1e4ddde2 Charles Yates
/** Process a frame.
213
*/
214 bee0d9e5 Charles Yates
215
void Process(void *ctx, AVPicture *picture, enum PixelFormat pix_fmt, int width, int height, int64_t pts)
216
{
217 1e4ddde2 Charles Yates
    int err = 0;
218 bee0d9e5 Charles Yates
    ContextInfo *ci = (ContextInfo *) ctx;
219
    AVPicture picture1;
220
    AVPicture picture2;
221
    AVPicture *pict = picture;
222 1e4ddde2 Charles Yates
    int out_width;
223
    int out_height;
224
    int i;
225
    uint8_t *ptr = NULL;
226
    FILE *in = rwpipe_reader( ci->rw );
227
    FILE *out = rwpipe_writer( ci->rw );
228
229
    /* Check that we have a pipe to talk to. */
230
    if ( in == NULL || out == NULL )
231
        err = 1;
232
233
    /* Convert to RGB24 if necessary */
234 115329f1 Diego Biurrun
    if ( !err && pix_fmt != PIX_FMT_RGB24 )
235 1e4ddde2 Charles Yates
    {
236
        int size = avpicture_get_size(PIX_FMT_RGB24, width, height);
237
238
        if ( size != ci->size1 )
239
        {
240
            av_free( ci->buf1 );
241
            ci->buf1 = av_malloc(size);
242
            ci->size1 = size;
243
            err = ci->buf1 == NULL;
244
        }
245
246
        if ( !err )
247
        {
248
            avpicture_fill(&picture1, ci->buf1, PIX_FMT_RGB24, width, height);
249
            if (img_convert(&picture1, PIX_FMT_RGB24, picture, pix_fmt, width, height) < 0)
250
                err = 1;
251
            pict = &picture1;
252
        }
253
    }
254
255
    /* Write out the PPM */
256
    if ( !err )
257
    {
258
        ptr = pict->data[ 0 ];
259
        fprintf( out, "P6\n%d %d\n255\n", width, height );
260
        for ( i = 0; !err && i < height; i ++ )
261
        {
262
            err = !fwrite( ptr, width * 3, 1, out );
263
            ptr += pict->linesize[ 0 ];
264 bee0d9e5 Charles Yates
        }
265 1e4ddde2 Charles Yates
        if ( !err )
266
            err = fflush( out );
267 bee0d9e5 Charles Yates
    }
268
269 1e4ddde2 Charles Yates
    /* Read the PPM returned. */
270
    if ( !err && !rwpipe_read_ppm_header( ci->rw, &out_width, &out_height ) )
271
    {
272 bee0d9e5 Charles Yates
        int size = avpicture_get_size(PIX_FMT_RGB24, out_width, out_height);
273 1e4ddde2 Charles Yates
274
        if ( size != ci->size2 )
275
        {
276
            av_free( ci->buf2 );
277
            ci->buf2 = av_malloc(size);
278
            ci->size2 = size;
279
            err = ci->buf2 == NULL;
280
        }
281
282
        if ( !err )
283
        {
284
            avpicture_fill(&picture2, ci->buf2, PIX_FMT_RGB24, out_width, out_height);
285
            ptr = picture2.data[ 0 ];
286
            for ( i = 0; !err && i < out_height; i ++ )
287
            {
288
                err = !fread( ptr, out_width * 3, 1, in );
289
                ptr += picture2.linesize[ 0 ];
290
            }
291 bee0d9e5 Charles Yates
        }
292 1e4ddde2 Charles Yates
    }
293 bee0d9e5 Charles Yates
294 1e4ddde2 Charles Yates
    /* Convert the returned PPM back to the input format */
295
    if ( !err )
296
    {
297
        /* Actually, this is wrong, since the out_width/out_height returned from the
298 115329f1 Diego Biurrun
         * filter won't necessarily be the same as width and height - img_resample
299
         * won't scale rgb24, so the only way out of this is to convert to something
300
         * that img_resample does like [which may or may not be pix_fmt], rescale
301 1e4ddde2 Charles Yates
         * and finally convert to pix_fmt... slow, but would provide the most flexibility.
302
         *
303
         * Currently, we take the upper left width/height pixels from the filtered image,
304
         * smaller images are going to be corrupted or cause a crash.
305
         *
306
         * Finally, what should we do in case of this call failing? Up to now, failures
307
         * are gracefully ignored and the original image is returned - in this case, a
308
         * failure may corrupt the input.
309
         */
310 115329f1 Diego Biurrun
        if (img_convert(picture, pix_fmt, &picture2, PIX_FMT_RGB24, width, height) < 0)
311 1e4ddde2 Charles Yates
        {
312
        }
313
    }
314 bee0d9e5 Charles Yates
}
315
316 1e4ddde2 Charles Yates
/** Clean up the effect.
317
*/
318
319 bee0d9e5 Charles Yates
void Release(void *ctx)
320
{
321
    ContextInfo *ci;
322
    ci = (ContextInfo *) ctx;
323
324
    if (ctx)
325 1e4ddde2 Charles Yates
    {
326
        rwpipe_close( ci->rw );
327
        av_free( ci->buf1 );
328
        av_free( ci->buf2 );
329 bee0d9e5 Charles Yates
        av_free(ctx);
330 1e4ddde2 Charles Yates
    }
331 bee0d9e5 Charles Yates
}