84
91
this->reader = fdopen( input[ 0 ], "r" );
85
92
this->writer = fdopen( output[ 1 ], "w" );
92
99
/** Read data from the pipe.
95
FILE *rwpipe_reader( rwpipe *this )
102
static FILE *rwpipe_reader( rwpipe *this )
103
110
/** Write data to the pipe.
106
FILE *rwpipe_writer( rwpipe *this )
113
static FILE *rwpipe_writer( rwpipe *this )
121
/* Read a number from the pipe - assumes PNM style headers.
124
static int rwpipe_read_number( rwpipe *rw )
128
FILE *in = rwpipe_reader( rw );
134
while( c != EOF && !isdigit( c ) && c != '#' )
138
while( c != EOF && c != '\n' )
141
while ( c != EOF && !isdigit( c ) );
143
while( c != EOF && isdigit( c ) )
145
value = value * 10 + ( c - '0' );
152
/** Read a PPM P6 header.
155
static int rwpipe_read_ppm_header( rwpipe *rw, int *width, int *height )
158
FILE *in = rwpipe_reader( rw );
161
fgets( line, 3, in );
162
if ( !strncmp( line, "P6", 2 ) )
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;
114
172
/** Close the pipe and process.
117
void rwpipe_close( rwpipe *this )
121
fclose( this->reader );
122
fclose( this->writer );
123
waitpid( this->pid, NULL, 0 );
175
static void rwpipe_close( rwpipe *this )
179
fclose( this->reader );
180
fclose( this->writer );
181
waitpid( this->pid, NULL, 0 );
186
/** Context info for this vhook - stores the pipe and image buffers.
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;
205
/** Initialise the context info for this vhook.
134
208
int Configure(void **ctxp, int argc, char *argv[])
136
*ctxp = av_mallocz(sizeof(ContextInfo));
137
if ( ctxp != NULL && argc > 1 )
139
ContextInfo *info = (ContextInfo *)*ctxp;
140
info->rw = rwpipe_open( argc - 1, &argv[ 1 ] );
145
int rwpipe_read_number( rwpipe *rw )
149
FILE *in = rwpipe_reader( rw );
155
while( c != EOF && !isdigit( c ) && c != '#' )
159
while( c != EOF && c != '\n' )
162
while ( c != EOF && !isdigit( c ) );
164
while( c != EOF && isdigit( c ) )
166
value = value * 10 + ( c - '0' );
173
int rwpipe_read_ppm_header( rwpipe *rw, int *width, int *height )
176
FILE *in = rwpipe_reader( rw );
179
fgets( line, 3, in );
180
if ( !strncmp( line, "P6", 2 ) )
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;
212
*ctxp = av_mallocz(sizeof(ContextInfo));
213
if ( ctxp != NULL && argc > 1 )
215
ContextInfo *info = (ContextInfo *)*ctxp;
216
info->rw = rwpipe_open( argc - 1, &argv[ 1 ] );
190
226
void Process(void *ctx, AVPicture *picture, enum PixelFormat pix_fmt, int width, int height, int64_t pts)
193
229
ContextInfo *ci = (ContextInfo *) ctx;
196
230
AVPicture picture1;
197
231
AVPicture picture2;
198
232
AVPicture *pict = picture;
203
FILE *in = rwpipe_reader( ci->rw );
204
FILE *out = rwpipe_writer( ci->rw );
206
/* Convert to RGB24 if necessary */
207
if (pix_fmt != PIX_FMT_RGB24) {
210
size = avpicture_get_size(PIX_FMT_RGB24, width, height);
211
buf1 = av_malloc(size);
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) {
221
/* Write out the PPM */
224
ptr = pict->data[ 0 ];
225
fprintf( out, "P6\n%d %d\n255\n", width, height );
226
for ( i = 0; !err && i < height; i ++ )
228
err = !fwrite( ptr, width * 3, 1, out );
229
ptr += pict->linesize[ 0 ];
235
/* Read the PPM returned. */
236
if ( !err && !rwpipe_read_ppm_header( ci->rw, &out_width, &out_height ) )
237
FILE *in = rwpipe_reader( ci->rw );
238
FILE *out = rwpipe_writer( ci->rw );
240
/* Check that we have a pipe to talk to. */
241
if ( in == NULL || out == NULL )
244
/* Convert to RGB24 if necessary */
245
if ( !err && pix_fmt != PIX_FMT_RGB24 )
247
int size = avpicture_get_size(PIX_FMT_RGB24, width, height);
249
if ( size != ci->size1 )
252
ci->buf1 = av_malloc(size);
254
err = ci->buf1 == NULL;
259
avpicture_fill(&picture1, ci->buf1, PIX_FMT_RGB24, width, height);
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");
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);
282
/* Write out the PPM */
285
ptr = pict->data[ 0 ];
286
fprintf( out, "P6\n%d %d\n255\n", width, height );
287
for ( i = 0; !err && i < height; i ++ )
289
err = !fwrite( ptr, width * 3, 1, out );
290
ptr += pict->linesize[ 0 ];
296
/* Read the PPM returned. */
297
if ( !err && !rwpipe_read_ppm_header( ci->rw, &out_width, &out_height ) )
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 ++ )
244
err = !fread( ptr, out_width * 3, 1, in );
245
ptr += picture2.linesize[ 0 ];
249
/* Convert the returned PPM back to the input format */
252
if (img_convert(picture, pix_fmt, &picture2, PIX_FMT_RGB24, width, height) < 0) {
301
if ( size != ci->size2 )
304
ci->buf2 = av_malloc(size);
306
err = ci->buf2 == NULL;
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 ++ )
315
err = !fread( ptr, out_width * 3, 1, in );
316
ptr += picture2.linesize[ 0 ];
321
/* Convert the returned PPM back to the input format */
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.
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");
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);
349
/** Clean up the effect.
260
352
void Release(void *ctx)
263
355
ci = (ContextInfo *) ctx;
267
rwpipe_close( ci->rw );
359
rwpipe_close( ci->rw );
362
sws_freeContext(ci->toRGB_convert_ctx);
363
sws_freeContext(ci->fromRGB_convert_ctx);