+ return mlt_deque_pop_back( this->stack_image );
+}
+
+/** Push a service.
+ *
+ * \public \memberof mlt_frame_s
+ * \param this a frame
+ * \param that an opaque pointer
+ * \return true if error
+ */
+
+int mlt_frame_push_service( mlt_frame this, void *that )
+{
+ return mlt_deque_push_back( this->stack_image, that );
+}
+
+/** Pop a service.
+ *
+ * \public \memberof mlt_frame_s
+ * \param this a frame
+ * \return an opaque pointer to something previously pushed
+ */
+
+void *mlt_frame_pop_service( mlt_frame this )
+{
+ return mlt_deque_pop_back( this->stack_image );
+}
+
+/** Push a number.
+ *
+ * \public \memberof mlt_frame_s
+ * \param this a frame
+ * \param that an integer
+ * \return true if error
+ */
+
+int mlt_frame_push_service_int( mlt_frame this, int that )
+{
+ return mlt_deque_push_back_int( this->stack_image, that );
+}
+
+/** Pop a number.
+ *
+ * \public \memberof mlt_frame_s
+ * \param this a frame
+ * \return an integer that was previously pushed
+ */
+
+int mlt_frame_pop_service_int( mlt_frame this )
+{
+ return mlt_deque_pop_back_int( this->stack_image );
+}
+
+/** Push an audio item on the stack.
+ *
+ * \public \memberof mlt_frame_s
+ * \param this a frame
+ * \param that an opaque pointer
+ * \return true if error
+ */
+
+int mlt_frame_push_audio( mlt_frame this, void *that )
+{
+ return mlt_deque_push_back( this->stack_audio, that );
+}
+
+/** Pop an audio item from the stack
+ *
+ * \public \memberof mlt_frame_s
+ * \param this a frame
+ * \return an opaque pointer to something that was pushed onto the frame's audio stack
+ */
+
+void *mlt_frame_pop_audio( mlt_frame this )
+{
+ return mlt_deque_pop_back( this->stack_audio );
+}
+
+/** Return the service stack
+ *
+ * \public \memberof mlt_frame_s
+ * \param this a frame
+ * \return the service stack
+ */
+
+mlt_deque mlt_frame_service_stack( mlt_frame this )
+{
+ return this->stack_service;
+}
+
+/** Replace image stack with the information provided.
+ *
+ * This might prove to be unreliable and restrictive - the idea is that a transition
+ * which normally uses two images may decide to only use the b frame (ie: in the case
+ * of a composite where the b frame completely obscures the a frame).
+ *
+ * The image must be writable and the destructor for the image itself must be taken
+ * care of on another frame and that frame cannot have a replace applied to it...
+ * Further it assumes that no alpha mask is in use.
+ *
+ * For these reasons, it can only be used in a specific situation - when you have
+ * multiple tracks each with their own transition and these transitions are applied
+ * in a strictly reversed order (ie: highest numbered [lowest track] is processed
+ * first).
+ *
+ * More reliable approach - the cases should be detected during the process phase
+ * and the upper tracks should simply not be invited to stack...
+ *
+ * \public \memberof mlt_frame_s
+ * \param this a frame
+ * \param image a new image
+ * \param format the image format
+ * \param width the width of the new image
+ * \param height the height of the new image
+ */
+
+void mlt_frame_replace_image( mlt_frame this, uint8_t *image, mlt_image_format format, int width, int height )
+{
+ // Remove all items from the stack
+ while( mlt_deque_pop_back( this->stack_image ) ) ;
+
+ // Update the information
+ mlt_properties_set_data( MLT_FRAME_PROPERTIES( this ), "image", image, 0, NULL, NULL );
+ mlt_properties_set_int( MLT_FRAME_PROPERTIES( this ), "width", width );
+ mlt_properties_set_int( MLT_FRAME_PROPERTIES( this ), "height", height );
+ mlt_properties_set_int( MLT_FRAME_PROPERTIES( this ), "format", format );
+ this->get_alpha_mask = NULL;
+}
+
+/** Get the short name for an image format.
+ *
+ * \public \memberof mlt_frame_s
+ * \param format the image format
+ * \return a string
+ */
+
+const char * mlt_image_format_name( mlt_image_format format )
+{
+ switch ( format )
+ {
+ case mlt_image_none: return "none";
+ case mlt_image_rgb24: return "rgb24";
+ case mlt_image_rgb24a: return "rgb24a";
+ case mlt_image_yuv422: return "yuv422";
+ case mlt_image_yuv420p: return "yuv420p";
+ case mlt_image_opengl: return "opengl";
+ case mlt_image_rgb24_full: return "rgb24_full";
+ case mlt_image_rgb24a_full: return "rgb24a_full";
+ case mlt_image_yuv422_709: return "yuv422_709";
+ }
+ return "invalid";