]> git.sesse.net Git - mlt/blob - src/framework/mlt_transition.c
westley/libxml2 mods, mcdv/mpeg release integration
[mlt] / src / framework / mlt_transition.c
1 /*
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>
5  *
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.
10  *
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.
15  *
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.
19  */
20
21 #include "config.h"
22
23 #include "mlt_transition.h"
24 #include "mlt_frame.h"
25
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29
30 /** Forward references.
31 */
32
33 static int transition_get_frame( mlt_service this, mlt_frame_ptr frame, int index );
34
35 /** Constructor.
36 */
37
38 int mlt_transition_init( mlt_transition this, void *child )
39 {
40         mlt_service service = &this->parent;
41         memset( this, 0, sizeof( struct mlt_transition_s ) );
42         this->child = child;
43         if ( mlt_service_init( service, this ) == 0 )
44         {
45                 mlt_properties properties = mlt_transition_properties( this );
46
47                 service->get_frame = transition_get_frame;
48
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 );
53                 mlt_properties_set( properties, "resource", "<transition>" );
54
55                 return 0;
56         }
57         return 1;
58 }
59
60 /** Get the service associated to the transition.
61 */
62
63 mlt_service mlt_transition_service( mlt_transition this )
64 {
65         return &this->parent;
66 }
67
68 /** Get the properties interface.
69 */
70
71 mlt_properties mlt_transition_properties( mlt_transition this )
72 {
73         return mlt_service_properties( mlt_transition_service( this ) );
74 }
75
76 /** Connect this transition with a producers a and b tracks.
77 */
78
79 int mlt_transition_connect( mlt_transition this, mlt_service producer, int a_track, int b_track )
80 {
81         int ret = mlt_service_connect_producer( &this->parent, producer, a_track );
82         if ( ret == 0 )
83         {
84                 mlt_properties properties = mlt_transition_properties( this );
85                 this->producer = producer;
86                 mlt_properties_set_int( properties, "a_track", a_track );
87                 mlt_properties_set_int( properties, "b_track", b_track );
88         }
89         return ret;
90 }
91
92 /** Set the in and out points.
93 */
94
95 void mlt_transition_set_in_and_out( mlt_transition this, mlt_position in, mlt_position out )
96 {
97         mlt_properties properties = mlt_transition_properties( this );
98         mlt_properties_set_position( properties, "in", in );
99         mlt_properties_set_position( properties, "out", out );
100 }
101
102 /** Get the index of the a track.
103 */
104
105 int mlt_transition_get_a_track( mlt_transition this )
106 {
107         return mlt_properties_get_int( mlt_transition_properties( this ), "a_track" );
108 }
109
110 /** Get the index of the b track.
111 */
112
113 int mlt_transition_get_b_track( mlt_transition this )
114 {
115         return mlt_properties_get_int( mlt_transition_properties( this ), "b_track" );
116 }
117
118 /** Get the in point.
119 */
120
121 mlt_position mlt_transition_get_in( mlt_transition this )
122 {
123         return mlt_properties_get_position( mlt_transition_properties( this ), "in" );
124 }
125
126 /** Get the out point.
127 */
128
129 mlt_position mlt_transition_get_out( mlt_transition this )
130 {
131         return mlt_properties_get_position( mlt_transition_properties( this ), "out" );
132 }
133
134 /** Process the frame.
135
136         If we have no process method (unlikely), we simply return the a_frame unmolested.
137 */
138
139 static mlt_frame transition_process( mlt_transition this, mlt_frame a_frame, mlt_frame b_frame )
140 {
141         if ( this->process == NULL )
142                 return a_frame;
143         else
144                 return this->process( this, a_frame, b_frame );
145 }
146
147 /** Get a frame from this filter.
148
149         The logic is complex here. A transition is applied to frames on the a and b tracks
150         specified in the connect method above. Since all frames are obtained via this 
151         method for all tracks, we have to take special care that we only obtain the a and
152         b frames once - we do this on the first call to get a frame from either a or b.
153         
154         After that, we have 2 cases to resolve:
155         
156         1)      if the track is the a_track and we're in the time zone, then we need to call the
157                 process method to do the effect on the frame and remember we've passed it on
158                 otherwise, we pass on the a_frame unmolested;
159         2)      For all other tracks, we get the frames on demand.
160 */
161
162 static int transition_get_frame( mlt_service service, mlt_frame_ptr frame, int index )
163 {
164         mlt_transition this = service->child;
165
166         mlt_properties properties = mlt_transition_properties( this );
167
168         int a_track = mlt_properties_get_int( properties, "a_track" );
169         int b_track = mlt_properties_get_int( properties, "b_track" );
170         mlt_position in = mlt_properties_get_position( properties, "in" );
171         mlt_position out = mlt_properties_get_position( properties, "out" );
172
173         if ( ( index == a_track || index == b_track ) && !( this->a_held || this->b_held ) )
174         {
175                 mlt_service_get_frame( this->producer, &this->a_frame, a_track );
176                 mlt_service_get_frame( this->producer, &this->b_frame, b_track );
177                 this->a_held = 1;
178                 this->b_held = 1;
179         }
180         
181         // Special case track processing
182         if ( index == a_track )
183         {
184                 // Determine if we're in the right time zone
185                 mlt_position position = mlt_frame_get_position( this->a_frame );
186                 if ( position >= in && position <= out )
187                 {
188                         // Process the transition
189                         *frame = transition_process( this, this->a_frame, this->b_frame );
190                         this->a_held = 0;
191                 }
192                 else
193                 {
194                         // Pass on the 'a frame' and remember that we've done it
195                         *frame = this->a_frame;
196                         this->a_held = 0;
197                 }
198                 return 0;
199         }
200         if ( index == b_track )
201         {
202                 // Pass on the 'b frame' and remember that we've done it
203                 *frame = this->b_frame;
204                 this->b_held = 0;
205                 return 0;
206         }
207         else
208         {
209                 // Pass through
210                 return mlt_service_get_frame( this->producer, frame, index );
211         }
212 }
213
214 /** Close the transition.
215 */
216
217 void mlt_transition_close( mlt_transition this )
218 {
219         if ( this->close != NULL )
220                 this->close( this );
221         else
222                 mlt_service_close( &this->parent );
223 }