2 * producer_framebuffer.c -- create subspeed frames
3 * Copyright (C) 2007 Jean-Baptiste Mardelle <jb@ader.ch>
4 * Author: Jean-Baptiste Mardelle, based on the code of motion_est by Zachary Drew
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #include <framework/mlt.h>
30 // Forward references.
31 static int producer_get_frame( mlt_producer
this, mlt_frame_ptr frame
, int index
);
33 /** Image stack(able) method
36 static int framebuffer_get_image( mlt_frame
this, uint8_t **image
, mlt_image_format
*format
, int *width
, int *height
, int writable
)
39 // Get the filter object and properties
40 mlt_producer producer
= mlt_frame_pop_service( this );
41 mlt_frame first_frame
= mlt_frame_pop_service( this );
43 mlt_properties producer_properties
= MLT_PRODUCER_PROPERTIES( producer
);
45 // Frame properties objects
46 mlt_properties frame_properties
= MLT_FRAME_PROPERTIES( this );
47 mlt_properties first_frame_properties
= MLT_FRAME_PROPERTIES( first_frame
);
49 *width
= mlt_properties_get_int( frame_properties
, "width" );
50 *height
= mlt_properties_get_int( frame_properties
, "height" );
55 case mlt_image_yuv420p
:
56 size
= *width
* 3 * ( *height
+ 1 ) / 2;
59 size
= *width
* ( *height
+ 1 ) * 3;
62 *format
= mlt_image_yuv422
;
63 size
= *width
* ( *height
+ 1 ) * 2;
67 uint8_t *output
= mlt_properties_get_data( producer_properties
, "output_buffer", NULL
);
71 output
= mlt_pool_alloc( size
);
73 // Let someone else clean up
74 mlt_properties_set_data( producer_properties
, "output_buffer", output
, size
, mlt_pool_release
, NULL
);
77 uint8_t *first_image
= mlt_properties_get_data( first_frame_properties
, "image", NULL
);
79 // which frames are buffered?
83 if( first_image
== NULL
)
85 mlt_properties props
= MLT_FRAME_PROPERTIES( this );
86 mlt_properties test_properties
= MLT_FRAME_PROPERTIES( first_frame
);
87 mlt_properties_set_double( test_properties
, "consumer_aspect_ratio", mlt_properties_get_double( props
, "consumer_aspect_ratio" ) );
88 mlt_properties_set( test_properties
, "rescale.interp", mlt_properties_get( props
, "rescale.interp" ) );
90 error
= mlt_frame_get_image( first_frame
, &first_image
, format
, width
, height
, writable
);
93 fprintf(stderr
, "first_image == NULL get image died\n");
98 // Start with a base image
99 memcpy( output
, first_image
, size
);
102 mlt_properties_set_data( frame_properties
, "image", output
, size
, NULL
, NULL
);
104 // Make sure that no further scaling is done
105 mlt_properties_set( frame_properties
, "rescale.interps", "none" );
106 mlt_properties_set( frame_properties
, "scale", "off" );
108 mlt_frame_close( first_frame
);
113 static int producer_get_frame( mlt_producer
this, mlt_frame_ptr frame
, int index
)
115 // Construct a new frame
116 *frame
= mlt_frame_init( MLT_PRODUCER_SERVICE( this ) );
117 mlt_properties properties
= MLT_PRODUCER_PROPERTIES( this );
121 mlt_frame first_frame
= mlt_properties_get_data( properties
, "first_frame", NULL
);
123 mlt_position first_position
= (first_frame
!= NULL
) ?
mlt_frame_get_position( first_frame
) : -1;
125 // Get the real producer
126 mlt_producer real_producer
= mlt_properties_get_data( properties
, "producer", NULL
);
129 int strobe
= mlt_properties_get_int( properties
, "strobe");
130 int freeze
= mlt_properties_get_int( properties
, "freeze");
131 int freeze_after
= mlt_properties_get_int( properties
, "freeze_after");
132 int freeze_before
= mlt_properties_get_int( properties
, "freeze_before");
134 mlt_position need_first
;
136 if (!freeze
|| freeze_after
|| freeze_before
) {
137 double prod_speed
= mlt_properties_get_double( properties
, "_speed");
138 double actual_position
= prod_speed
* (double) mlt_producer_position( this );
140 if (mlt_properties_get_int( properties
, "reverse")) actual_position
= mlt_producer_get_playtime(this) - actual_position
;
144 need_first
= floor( actual_position
);
148 // Strobe effect wanted, calculate frame position
149 need_first
= floor( actual_position
);
150 need_first
-= need_first
%strobe
;
154 if (freeze_after
&& need_first
> freeze
) need_first
= freeze
;
155 else if (freeze_before
&& need_first
< freeze
) need_first
= freeze
;
158 else need_first
= freeze
;
160 if( need_first
!= first_position
)
162 mlt_frame_close( first_frame
);
167 if( first_frame
== NULL
)
169 // Seek the producer to the correct place
170 mlt_producer_seek( real_producer
, need_first
);
173 mlt_service_get_frame( MLT_PRODUCER_SERVICE( real_producer
), &first_frame
, index
);
176 // Make sure things are in their place
177 mlt_properties_set_data( properties
, "first_frame", first_frame
, 0, NULL
, NULL
);
179 // Stack the producer and producer's get image
180 mlt_frame_push_service( *frame
, first_frame
);
181 mlt_properties_inc_ref( MLT_FRAME_PROPERTIES( first_frame
) );
183 mlt_frame_push_service( *frame
, this );
184 mlt_frame_push_service( *frame
, framebuffer_get_image
);
187 // Give the returned frame temporal identity
188 mlt_frame_set_position( *frame
, mlt_producer_position( this ) );
195 mlt_producer
producer_framebuffer_init( mlt_profile profile
, mlt_service_type type
, const char *id
, char *arg
)
198 mlt_producer
this = NULL
;
199 this = calloc( 1, sizeof( struct mlt_producer_s
) );
200 mlt_producer_init( this, NULL
);
203 mlt_producer real_producer
;
205 // Check if a speed was specified.
208 * Speed must be appended to the filename with ':'. To play your video at 50%:
209 inigo framebuffer:my_video.mpg:0.5
211 * Stroboscope effect can be obtained by adding a stobe=x parameter, where
212 x is the number of frames that will be ignored.
214 * You can play the movie backwards by adding reverse=1
216 * You can freeze the clip at a determined position by adding freeze=frame_pos
217 add freeze_after=1 to freeze only paste position or freeze_before to freeze before it
224 char *props
= strdup( arg
);
226 count
= strcspn( ptr
, "?" );
228 real_producer
= mlt_factory_producer( profile
, "fezzik", props
);
231 ptr
+= strspn( ptr
, "?" );
232 count
= strcspn( ptr
, "?" );
237 if (speed
== 0.0) speed
= 1.0;
240 if ( this != NULL
&& real_producer
!= NULL
)
242 // Get the properties of this producer
243 mlt_properties properties
= MLT_PRODUCER_PROPERTIES( this );
245 // Fezzik normalised it for us already
246 mlt_properties_set_int( properties
, "fezzik_normalised", 1);
247 mlt_properties_set( properties
, "resource", arg
);
249 // Store the producer and fitler
250 mlt_properties_set_data( properties
, "producer", real_producer
, 0, ( mlt_destructor
)mlt_producer_close
, NULL
);
252 // Grab some stuff from the real_producer
253 mlt_properties_pass_list( properties
, MLT_PRODUCER_PROPERTIES( real_producer
), "length, width,height" );
258 double real_length
= (double) mlt_producer_get_length( real_producer
);
259 mlt_properties_set_position( properties
, "length", real_length
/ speed
);
262 // Since we control the seeking, prevent it from seeking on its own
263 mlt_producer_set_speed( real_producer
, 0 );
264 mlt_producer_set_speed( this, speed
);
266 // Override the get_frame method
267 this->get_frame
= producer_get_frame
;
272 mlt_producer_close( this );
274 mlt_producer_close( real_producer
);