3232#include <kos/anno.h>
3333#include <kos/refcnt.h>
3434
35+ #include "../color.h"
3536#include "../types.h"
3637
3738#ifdef __CC__
@@ -43,110 +44,105 @@ struct video_anim;
4344
4445typedef __uint32_t video_anim_frame_id ;
4546
46- struct video_anim_frameinfo {
47- struct __timeval64 vafi_showfor ; /* How long to display the frame before showing the next */
48- video_anim_frame_id vafi_frameid ; /* ID (# of frames that came before) of the associated frame */
47+ /* Frame data created when the first frame is read, and updated whenever a next frame is read.
48+ * You must treat this data as READ-ONLY if you ever intend to call `video_anim_nextframe()'
49+ * using this data again. */
50+ struct video_anim_frame {
51+ __ATTR_NONNULL_T ((1 )) void /* Destructor callback for frame data */
52+ (LIBVIDEO_GFX_CC * vaf_fini )(struct video_anim_frame * __restrict __self );
53+ REF struct video_buffer * vaf_frame ; /* [1..1] Current frame (and previous frame during) */
54+ struct __timeval64 vaf_showfor ; /* How long to display the frame before showing the next */
55+ video_anim_frame_id vaf_frameid ; /* ID of this frame */
56+ video_color_t vaf_colorkey ; /* Frame color key, or "0" if not needed */
57+
58+ /* Animation-specific frame data goes here... */
4959};
5060
61+ #define video_anim_frame_fini (self ) ((self)->vaf_fini)(self)
62+
63+
5164struct video_anim_ops {
5265 __ATTR_NONNULL_T ((1 )) void
5366 (LIBVIDEO_GFX_CC * vao_destroy )(struct video_anim * __restrict __self );
5467
55- /* Start a new animation cycle and return a video buffer for the first frame.
56- * - The video contents of the returned buffer should NOT be modified.
68+ /* Size of `struct video_anim_frame' that the
69+ * caller must use with this type of animation. */
70+ size_t vao_sizeof_frame ;
71+
72+ /* Start a new animation cycle and initialize `__frame' for the first frame.
73+ * - The video contents of the buffer included in `__frame' should NOT be modified.
5774 * - Make a call to `vao_nextframe()' to advance to the next frame.
75+ * - Once done, finalize frame data using `video_anim_frame_fini(__frame)'
76+ * - The given `__frame' must be at least `vao_sizeof_frame' bytes large,
77+ * and be aligned according to standard alignment (`alloca()' and `malloc()'
78+ * are both fine for allocating this buffer))
5879 *
5980 * To render the animation, the caller should do this:
60- * >> struct video_anim_frameinfo info, nextinfo;
61- * >> REF struct video_screen *screen = screen_buffer_create(NULL);
62- * >> REF struct video_anim *anim = video_anim_open("/vat/anim.gif");
63- * >> REF struct video_buffer *frame = video_anim_firstframe(anim, &info);
6481 * >> struct video_gfx screen_gfx;
6582 * >> struct video_gfx frame_gfx;
6683 * >> struct timeval frame_start, frame_end;
67- * >> struct timeval tv_delay, tv_spent;
84+ * >> struct timeval tv_delay, tv_spent, showfor ;
6885 * >> struct timespec ts_delay;
86+ * >> REF struct video_screen *screen;
87+ * >> REF struct video_anim *anim;
88+ * >> struct video_anim_frame *data;
89+ * >>
90+ * >> screen = screen_buffer_create(NULL);
91+ * >> anim = video_anim_open("/var/anim.gif");
92+ * >> data = (struct video_anim_frame *)malloca(video_anim_sizeof_frame(anim));
93+ * >>
94+ * >> video_anim_firstframe(anim, data);
6995 * >> video_buffer_getgfx((struct video_buffer *)screen, &screen_gfx,
7096 * >> GFX_BLENDMODE_OVERRIDE, VIDEO_GFX_F_NORMAL, 0);
7197 * >> gettimeofday(&frame_start, NULL);
7298 * >> for (;;) {
7399 * >>
74100 * >> // Display current frame on-screen (here: stretched)
75- * >> video_buffer_getgfx(frame , &frame_gfx,
101+ * >> video_buffer_getgfx(data->vaf_frame , &frame_gfx,
76102 * >> GFX_BLENDMODE_OVERRIDE, VIDEO_GFX_F_NORMAL, 0);
77103 * >> video_gfx_stretch(&screen_gfx, 0, 0, VIDEO_DIM_MAX, VIDEO_DIM_MAX,
78104 * >> &frame_gfx, 0, 0, VIDEO_DIM_MAX, VIDEO_DIM_MAX);
79105 * >> struct video_crect update_rect = VIDEO_CRECT_INIT_FULL;
80106 * >> screen_buffer_updaterect(screen, &update_rect);
81107 * >>
82108 * >> // Load next frame as part of render delay
83- * >> nextinfo = info ;
84- * >> video_anim_nextframe(&anim, frame, &nextinfo );
109+ * >> showfor = data->vaf_showfor ;
110+ * >> video_anim_nextframe(&anim, data );
85111 * >>
86112 * >> // Wait until the next frame should be rendered
87113 * >> gettimeofday(&frame_end, NULL);
88114 * >> timeval_sub(&tv_spent, &frame_end, &frame_start);
89- * >> timeval_sub(&tv_delay, &info.vafi_showfor , &tv_spent);
115+ * >> timeval_sub(&tv_delay, &showfor , &tv_spent);
90116 * >> timeval_add(&frame_end, &frame_end, &tv_delay);
91117 * >> TIMEVAL_TO_TIMESPEC(&tv_delay, &ts_delay);
92118 * >> frame_start = frame_end;
93- * >> info = nextinfo;
94119 * >> if (ts_delay.tv_sec >= 0)
95120 * >> nanosleep(&ts_delay, NULL);
96121 * >> }
97122 *
98- * @return: * : A video buffer containing the first frame of the animation
99- * If you do not intend to render any of the other frame, you
100- * can simply decref() the animation and use this buffer as you
101- * would one returned by `video_buffer_open()'
102- * @return: NULL: Failed to load first frame (s.a. `errno') */
103- __ATTR_WUNUSED_T __ATTR_IN_T (1 ) __ATTR_OUT_T (2 ) __REF struct video_buffer *
123+ * @return: 0 : Success: `__frame' was initialized and the caller must eventually finalize it
124+ * @return: -1: Failed to load first frame (s.a. `errno') */
125+ __ATTR_WUNUSED_T __ATTR_IN_T (1 ) __ATTR_OUT_T (2 ) int
104126 (LIBVIDEO_GFX_CC * vao_firstframe )(struct video_anim const * __restrict __self ,
105- struct video_anim_frameinfo * __restrict __info );
127+ struct video_anim_frame * __restrict __frame );
106128
107- /* Update pixel data of `__buf' to contain the contents of the next frame in line.
108- * For this purpose, assume that on entry, `__buf' was returned by `vao_firstframe'
109- * or a preceding call to `vao_nextframe', and currently contains a redner of the
110- * frame identified by `IN(__info->vafi_frameid)'.
111- *
112- * This function may then update the contents of `__buf' and `__info' such that
113- * upon successful return (return == 0), `__info->vafi_frameid' has been increment
114- * or reset back to `0', and `__buf' now contains a render of the next frame. It
115- * may also simply return some other video buffer (iow: return != __buf) is allowed
116- *
117- * CAUTION: This function is not thread-safe when `__buf' is simultaneously being
118- * used by another thread, or if someone is still holding a video_lock.
119- * This function is also allowed to modify `__buf' in way not normally
120- * allowed (including changing its codec and/or palette, as well as the
121- * memory used to back any potential video lock). The only thing it is
122- * not allowed to changed are the buffer's dimensions.
123- *
124- * CAUTION: The video buffer returned by `vao_firstframe' might contain some extra
125- * out-of-band data that is then needed/used by this function to render
126- * the next frame. Do **NOT** pass a video buffer that wasn't returned by
127- * `vao_firstframe', and do **NOT** try to skip frames by changing the
128- * value in `__info->vafi_frameid' between calls.
129+ /* Update `__frame' (and specifically: `__frame->vaf_frame') to contain the contents
130+ * of the next frame in line.
129131 *
130- * @return: * : A video buffer with the same resolution as `__buf' (or possibly
131- * just `__buf' again), that contains a render of the next frame.
132- * In this case, this function semantically inherited a reference
133- * to the given `__buf' (meaning that if another buffer is returned,
134- * the call will have video_buffer_decref'd the given `__buf')
135- * @return: NULL: Failed to render next frame (s.a. `errno'). In this case, no
136- * reference to `__buf' has been inherited, though the pixel
137- * contents of `__buf' may have been modified and may even look
138- * corrupted now (though semantically speaking, `__buf' is still
139- * guarantied to be in a consistent state). */
140- __ATTR_WUNUSED_T __ATTR_IN_T (1 ) __ATTR_INOUT_T (2 ) __ATTR_INOUT_T (3 ) __REF struct video_buffer *
132+ * @return: 0 : Success: `__frame' was updated to contain the next frame.
133+ * @return: -1: Failed to render next frame (s.a. `errno'). In this case, no
134+ * reference to `__buf' has been inherited, though the pixel
135+ * contents of `__buf' may have been modified and may even look
136+ * corrupted now (though semantically speaking, `__buf' is still
137+ * guarantied to be in a consistent state). */
138+ __ATTR_WUNUSED_T __ATTR_IN_T (1 ) __ATTR_INOUT_T (2 ) int
141139 (LIBVIDEO_GFX_CC * vao_nextframe )(struct video_anim const * __restrict __self ,
142- /*inherit(on_success)*/ __REF struct video_buffer * __restrict __buf ,
143- struct video_anim_frameinfo * __restrict __info );
140+ struct video_anim_frame * __restrict __frame );
144141};
145142
146- #define video_anim_firstframe (self , info ) \
147- (* (self )-> va_ops -> vao_firstframe )(self , info )
148- #define video_anim_nextframe (self , buf , info ) \
149- (* (self )-> va_ops -> vao_nextframe )(self , buf , info )
143+ #define video_anim_sizeof_frame (self ) ((self)->va_ops->vao_sizeof_frame)
144+ #define video_anim_firstframe (self , frame ) (*(self)->va_ops->vao_firstframe)(self, frame)
145+ #define video_anim_nextframe (self , frame ) (*(self)->va_ops->vao_nextframe)(self, frame)
150146
151147struct video_anim {
152148 struct video_anim_ops const * va_ops ; /* [1..1][const] Video animation operators */
0 commit comments