2 * mlt_transition.c -- abstraction for all transition services
3 * Copyright (C) 2003-2004 Ushodaya Enterprises Limited
4 * Author: Charles Yates <charles.yates@pandora.be>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program 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
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 #include "mlt_transition.h"
24 #include "mlt_frame.h"
30 /** Forward references.
33 static int transition_get_frame( mlt_service
this, mlt_frame_ptr frame
, int index
);
38 int mlt_transition_init( mlt_transition
this, void *child
)
40 mlt_service service
= &this->parent
;
41 memset( this, 0, sizeof( struct mlt_transition_s
) );
43 if ( mlt_service_init( service
, this ) == 0 )
45 mlt_properties properties
= mlt_transition_properties( this );
47 service
->get_frame
= transition_get_frame
;
49 mlt_properties_set_position( properties
, "in", 0 );
50 mlt_properties_set_position( properties
, "out", 0 );
51 mlt_properties_set_int( properties
, "a_track", 0 );
52 mlt_properties_set_int( properties
, "b_track", 1 );
59 /** Create a new transition.
62 mlt_transition
mlt_transition_new( )
64 mlt_transition
this = calloc( 1, sizeof( struct mlt_transition_s
) );
66 mlt_transition_init( this, NULL
);
70 /** Get the service associated to the transition.
73 mlt_service
mlt_transition_service( mlt_transition
this )
78 /** Get the properties interface.
81 mlt_properties
mlt_transition_properties( mlt_transition
this )
83 return mlt_service_properties( mlt_transition_service( this ) );
86 /** Connect this transition with a producers a and b tracks.
89 int mlt_transition_connect( mlt_transition
this, mlt_service producer
, int a_track
, int b_track
)
91 int ret
= mlt_service_connect_producer( &this->parent
, producer
, a_track
);
94 mlt_properties properties
= mlt_transition_properties( this );
95 this->producer
= producer
;
96 mlt_properties_set_int( properties
, "a_track", a_track
);
97 mlt_properties_set_int( properties
, "b_track", b_track
);
102 /** Set the in and out points.
105 void mlt_transition_set_in_and_out( mlt_transition
this, mlt_position in
, mlt_position out
)
107 mlt_properties properties
= mlt_transition_properties( this );
108 mlt_properties_set_position( properties
, "in", in
);
109 mlt_properties_set_position( properties
, "out", out
);
112 /** Get the index of the a track.
115 int mlt_transition_get_a_track( mlt_transition
this )
117 return mlt_properties_get_int( mlt_transition_properties( this ), "a_track" );
120 /** Get the index of the b track.
123 int mlt_transition_get_b_track( mlt_transition
this )
125 return mlt_properties_get_int( mlt_transition_properties( this ), "b_track" );
128 /** Get the in point.
131 mlt_position
mlt_transition_get_in( mlt_transition
this )
133 return mlt_properties_get_position( mlt_transition_properties( this ), "in" );
136 /** Get the out point.
139 mlt_position
mlt_transition_get_out( mlt_transition
this )
141 return mlt_properties_get_position( mlt_transition_properties( this ), "out" );
144 /** Process the frame.
146 If we have no process method (unlikely), we simply return the a_frame unmolested.
149 mlt_frame
mlt_transition_process( mlt_transition
this, mlt_frame a_frame
, mlt_frame b_frame
)
151 if ( this->process
== NULL
)
154 return this->process( this, a_frame
, b_frame
);
157 /** Get a frame from this filter.
159 The logic is complex here. A transition is applied to frames on the a and b tracks
160 specified in the connect method above. Since all frames are obtained via this
161 method for all tracks, we have to take special care that we only obtain the a and
162 b frames once - we do this on the first call to get a frame from either a or b.
164 After that, we have 2 cases to resolve:
166 1) if the track is the a_track and we're in the time zone, then we need to call the
167 process method to do the effect on the frame and remember we've passed it on
168 otherwise, we pass on the a_frame unmolested;
169 2) For all other tracks, we get the frames on demand.
172 static int transition_get_frame( mlt_service service
, mlt_frame_ptr frame
, int index
)
174 mlt_transition
this = service
->child
;
176 mlt_properties properties
= mlt_transition_properties( this );
178 int a_track
= mlt_properties_get_int( properties
, "a_track" );
179 int b_track
= mlt_properties_get_int( properties
, "b_track" );
180 mlt_position in
= mlt_properties_get_position( properties
, "in" );
181 mlt_position out
= mlt_properties_get_position( properties
, "out" );
183 if ( ( index
== a_track
|| index
== b_track
) && !( this->a_held
|| this->b_held
) )
185 mlt_service_get_frame( this->producer
, &this->a_frame
, a_track
);
186 mlt_service_get_frame( this->producer
, &this->b_frame
, b_track
);
191 // Special case track processing
192 if ( index
== a_track
)
194 // Determine if we're in the right time zone
195 mlt_position position
= mlt_frame_get_position( this->a_frame
);
196 if ( position
>= in
&& position
<= out
)
198 // Process the transition
199 *frame
= mlt_transition_process( this, this->a_frame
, this->b_frame
);
200 if ( !mlt_properties_get_int( mlt_frame_properties( this->a_frame
), "test_image" ) )
201 mlt_properties_set_int( mlt_frame_properties( this->b_frame
), "test_image", 1 );
202 if ( !mlt_properties_get_int( mlt_frame_properties( this->a_frame
), "test_audio" ) )
203 mlt_properties_set_int( mlt_frame_properties( this->b_frame
), "test_audio", 1 );
208 // Pass on the 'a frame' and remember that we've done it
209 *frame
= this->a_frame
;
214 if ( index
== b_track
)
216 // Pass on the 'b frame' and remember that we've done it
217 *frame
= this->b_frame
;
224 return mlt_service_get_frame( this->producer
, frame
, index
);
228 /** Close the transition.
231 void mlt_transition_close( mlt_transition
this )
233 if ( this->close
!= NULL
)
236 mlt_service_close( &this->parent
);