Initial git import
[sxemacs] / src / media / media.h
1 /* Media functions.
2    Copyright (C) 2006 Sebastian Freundt
3
4 This file is part of SXEmacs
5
6 SXEmacs 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 3 of the License, or
9 (at your option) any later version.
10
11 SXEmacs 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, see <http://www.gnu.org/licenses/>. */
18
19
20 /* Synched up with: Not in FSF. */
21
22 #ifndef INCLUDED_media_h_
23 #define INCLUDED_media_h_
24
25 #include "buffer.h"
26 #include "sysdep.h"
27 #include "lrecord.h"
28 #include "lstream.h"
29 #include "opaque.h"
30
31 #ifdef FILE_CODING
32 #include "mule/file-coding.h"
33 #endif
34 \f
35 typedef enum media_drivers media_driver;
36 typedef enum media_types media_type;
37 typedef enum media_kinds media_kind;
38
39 typedef struct mtype_audio_properties mtype_audio_properties;
40 typedef struct mtype_video_properties mtype_video_properties;
41 typedef struct mkind_file_properties mkind_file_properties;
42 typedef struct mkind_string_properties mkind_string_properties;
43
44 typedef struct Lisp_Media_Stream Lisp_Media_Stream;
45 typedef struct media_substream media_substream;
46
47 typedef void *ms_driver_data_t;
48 typedef ms_driver_data_t(*ms_open_fun)(Lisp_Media_Stream*);
49 typedef void(*ms_close_fun)(ms_driver_data_t);
50 typedef void(*ms_print_fun)(Lisp_Object stream, Lisp_Object, int);
51 typedef Lisp_Object(*ms_mark_fun)(ms_driver_data_t driver_data);
52 typedef size_t(*ms_read_fun)(media_substream*, void*, size_t);
53 typedef size_t(*ms_write_fun)(media_substream*, void*, size_t);
54 typedef void(*ms_rewind_fun)(media_substream*);
55 typedef void(*ms_seek_fun)(media_substream*, size_t);
56
57 typedef struct ms_meths ms_meths;
58 typedef struct media_data media_data;
59
60 /* audio coercion */
61 typedef int32_t sxe_media_sample_t;
62 typedef void* audio_coerce_args;
63 typedef size_t(*audio_coerce_fun)(sxe_media_sample_t *dst,
64                                   sxe_media_sample_t *src,
65                                   size_t len, void *args);
66 typedef void(*audio_resample_fun)(void *dst, void *src, size_t len);
67 typedef struct media_sample_format_s media_sample_format_t;
68 typedef struct audio_coerce_chain_s audio_coerce_chain_t;
69
70 \f
71 enum media_drivers {
72         MDRIVER_UNKNOWN,
73         MDRIVER_INTERNAL,
74         MDRIVER_SNDFILE,
75         MDRIVER_FFMPEG,
76         MDRIVER_MAD,
77         MDRIVER_SOX,
78         MDRIVER_XINE,
79         MDRIVER_GSTREAMER,
80         NUMBER_OF_MEDIA_DRIVERS
81 };
82
83 enum media_types {
84         MTYPE_UNKNOWN,
85         MTYPE_AUDIO,
86         MTYPE_VIDEO,
87         MTYPE_IMAGE,
88         NUMBER_OF_MEDIA_TYPES
89 };
90
91 enum media_kinds {
92         MKIND_UNKNOWN,
93         MKIND_FILE,
94         MKIND_STRING,           /* better name? */
95         MKIND_FIFO,
96         MKIND_STREAM,
97         NUMBER_OF_MEDIA_KINDS
98 };
99
100 /* type properties */
101 struct mtype_audio_properties {
102         const char *name;       /* name of the codec or whatever */
103         const char *codec_name; /* name of the codec or whatever */
104         uint16_t channels;
105         uint16_t samplewidth;   /* in bits */
106         uint32_t samplerate;
107         uint16_t framesize;     /* == channels * samplewidth (in bytes) */
108         media_sample_format_t *msf; /* function for upsampling */
109         int endianness;
110         int bitrate;
111 };
112
113 struct mtype_video_properties {
114         const char *name;       /* name of the codec or whatever */
115         const char *codec_name; /* name of the codec or whatever */
116         int bitrate;
117         int width;
118         int height;
119         int aspect_num, aspect_den;
120         uint16_t framesize;
121         int endianness;
122 };
123
124 /* kind properties */
125 struct mkind_file_properties {
126         Lisp_Object filename;
127         uint32_t filesize;
128 };
129
130 struct mkind_string_properties {
131         char *name;
132         char *stream_data;
133         uint32_t size;
134 };
135
136 \f
137 struct media_substream {
138         /* navigation for the doubly linked list */
139         media_substream *next;
140         media_substream *prev;
141         Lisp_Media_Stream *up;
142
143         /* data and handling issues */
144         media_type type; 
145
146         union {
147                 mtype_audio_properties *aprops;
148                 mtype_video_properties *vprops;
149         } type_properties;
150
151 #ifdef HAVE_THREADS
152         pthread_mutex_t substream_mutex;
153 #endif
154
155         /* anonymous data, used by the various backends */
156         /* do not use it, it is not freed by gc */
157         ms_driver_data_t substream_data;
158 };
159
160 #define media_substream_type(mss) (mss)->type
161 #define media_substream_type_properties(mss) (mss)->type_properties
162 #define media_substream_data(mss) (mss)->substream_data
163 /* make it look like funs */
164 #define media_substream_read(mss, b, r) (media_substream_sread(mss)(mss, b, r))
165 #define media_substream_rewind(mss) (media_substream_srewind(mss)(mss))
166
167 #define media_substream_next(mss) (mss)->next
168 #define media_substream_prev(mss) (mss)->prev
169 #define media_substream_up(mss) (mss)->up
170
171 \f
172 /* now stream driver dependent stuff */
173 struct ms_meths {
174         ms_open_fun open;
175         ms_close_fun close;
176         ms_print_fun print;
177         ms_mark_fun mark;
178         ms_read_fun read;
179         ms_write_fun write;
180         ms_rewind_fun rewind;
181         ms_seek_fun seek;
182 };
183
184 #define DECLARE_MEDIA_DRIVER(_name)                                     \
185         extern ms_meths _name[1]
186 #define DECLARE_MEDIA_DRIVER_OPEN_METH(_name)                           \
187         static ms_driver_data_t _name##_open(Lisp_Media_Stream*)
188 #define DECLARE_MEDIA_DRIVER_CLOSE_METH(_name)                          \
189         static void _name##_close(ms_driver_data_t)
190 #define DECLARE_MEDIA_DRIVER_PRINT_METH(_name)                          \
191         static void _name##_print(Lisp_Object, Lisp_Object, int);
192 #define DECLARE_MEDIA_DRIVER_MARK_METH(_name)                           \
193         static Lisp_Object _name##_mark(ms_driver_data_t);
194 #define DECLARE_MEDIA_DRIVER_READ_METH(_name)                           \
195         static size_t _name##_read(media_substream*, void*, size_t);
196 #define DECLARE_MEDIA_DRIVER_WRITE_METH(_name)                          \
197         static size_t _name##_write(media_substream*, void*, size_t);
198 #define DECLARE_MEDIA_DRIVER_REWIND_METH(_name)                         \
199         static void _name##_rewind(media_substream*);
200 #define DECLARE_MEDIA_DRIVER_SEEK_METH(_name)                           \
201         static void _name##_seek(media_substream*, size_t);
202 #define DECLARE_MEDIA_DRIVER_SIMPLE_METHS(_name)                        \
203         DECLARE_MEDIA_DRIVER_OPEN_METH(_name);                          \
204         DECLARE_MEDIA_DRIVER_CLOSE_METH(_name);                         \
205         DECLARE_MEDIA_DRIVER_PRINT_METH(_name);                         \
206         DECLARE_MEDIA_DRIVER_MARK_METH(_name);                          \
207         DECLARE_MEDIA_DRIVER_READ_METH(_name);                          \
208         DECLARE_MEDIA_DRIVER_WRITE_METH(_name);                         \
209         DECLARE_MEDIA_DRIVER_REWIND_METH(_name)                         \
210         DECLARE_MEDIA_DRIVER_SEEK_METH(_name);                          \
211         /* we currently have no write support so define a nop here */   \
212         static size_t                                                   \
213         _name##_write(media_substream *v01d, void *buf, size_t size)    \
214         {                                                               \
215                 return 0;                                               \
216         }                                                               \
217         /* we currently have no seek support so define a nop here */    \
218         static void                                                     \
219         _name##_seek(media_substream *v01d, size_t position)            \
220         {                                                               \
221                 return;                                                 \
222         }
223
224 #define DEFINE_MEDIA_DRIVER_CUSTOM(_n, _o, _c, _p, _m, _r, _w, _rw, _s) \
225         ms_meths _n[1] = { { (_o), (_c), (_p), (_m), (_r), (_w), (_rw), (_s) } }
226 #define DEFINE_MEDIA_DRIVER(_name, _o, _c, _p, _m, _r, _w, _rw, _s)     \
227         DEFINE_MEDIA_DRIVER_CUSTOM((_name),                             \
228                                    (_name##_##_o),                      \
229                                    (_name##_##_c),                      \
230                                    (_name##_##_p),                      \
231                                    (_name##_##_m),                      \
232                                    (_name##_##_r),                      \
233                                    (_name##_##_w),                      \
234                                    (_name##_##_rw),                     \
235                                    (_name##_##_s))
236 #define DEFINE_MEDIA_DRIVER_SIMPLE(_name)                               \
237         DEFINE_MEDIA_DRIVER(_name,                                      \
238                             open, close,                                \
239                             print, mark,                                \
240                             read, write,                                \
241                             rewind, seek)
242 #define DEFINE_MEDIA_DRIVER_EMPTY(_name)                                \
243         DEFINE_MEDIA_DRIVER_CUSTOM((_name),                             \
244                                    NULL, NULL,                          \
245                                    NULL, NULL,                          \
246                                    NULL, NULL,                          \
247                                    NULL, NULL)
248 #define SET_MEDIA_DRIVER_FUNCTION_CUSTOM(_driver, _slot, _function)     \
249         (_driver->_slot = _function)
250 #define SET_MEDIA_DRIVER_FUNCTION(_driver, _function)                   \
251         SET_MEDIA_DRIVER_FUNCTION_CUSTOM(_driver,                       \
252                                          _function,                     \
253                                          _driver##_##_function)
254
255 #define media_stream_set_meths(_ms, _m) ((_ms)->meths = _m)
256 #define media_stream_meths(_ms) ((_ms)->meths)
257 #define media_stream_meth(_ms, _m) (media_stream_meths(_ms)->_m)
258 #define XMEDIA_STREAM_SET_METHS(_ms, _m) (media_stream_set_meths(       \
259                                                   XMEDIA_STREAM(_ms), _m))
260 #define XMEDIA_STREAM_METHS(_ms) (media_stream_meths(XMEDIA_STREAM(_ms)))
261 #define XMEDIA_STREAM_METH(_ms, _m) (media_stream_meth(XMEDIA_STREAM(_ms), _m))
262
263 \f
264 /* Media streams are actually containers, we use doubly linked lists with media
265    substreams inside */
266 struct Lisp_Media_Stream {
267         struct lcrecord_header lheader;
268
269         media_substream *first; /* pointer to first substream */
270         media_substream *last;  /* pointer to last substream */
271
272         media_kind kind; 
273         media_driver driver;
274
275         union {
276                 mkind_file_properties *fprops;
277                 mkind_string_properties *sprops;
278         } kind_properties;
279
280         /* methods for the stream */
281         const ms_meths *meths;
282
283         /* anonymous data, used by the various backends */
284         void *stream_data;
285 };
286
287 extern Lisp_Object Qmedia_streamp;
288 extern Lisp_Object Qunknown;
289
290 DECLARE_LRECORD(media_stream, Lisp_Media_Stream);
291 #define XMEDIA_STREAM(x) XRECORD(x, media_stream, Lisp_Media_Stream)
292 #define XSETMEDIA_STREAM(x, p) XSETRECORD(x, p, media_stream)
293 #define wrap_media_stream(p) wrap_object(p)
294 #define MEDIA_STREAMP(x) RECORDP(x, media_stream)
295 #define CHECK_MEDIA_STREAM(x) CHECK_RECORD(x, media_stream)
296 #define CONCHECK_MEDIA_STREAM(x) CONCHECK_RECORD(x, media_stream)
297
298 #define media_stream_first(ms) (ms)->first
299 #define media_stream_last(ms) (ms)->last
300 #define media_stream_driver(ms) (ms)->driver
301 #define media_stream_kind(ms) (ms)->kind
302 #define media_stream_kind_properties(ms) (ms)->kind_properties
303 #define media_stream_data(ms) (ms)->stream_data
304 #define media_stream_1sub(ms) media_stream_first(ms)
305 #define media_stream_nsub(ms) media_stream_last(ms)
306 #define XMEDIA_STREAM_FIRST(x) media_stream_first(XMEDIA_STREAM(x))
307 #define XMEDIA_STREAM_LAST(x) media_stream_last(XMEDIA_STREAM(x))
308 #define XMEDIA_STREAM_DRIVER(x) media_stream_driver(XMEDIA_STREAM(x))
309 #define XMEDIA_STREAM_KIND(x) media_stream_kind(XMEDIA_STREAM(x))
310 #define XMEDIA_STREAM_DATA(x) media_stream_data(XMEDIA_STREAM(x))
311 #define XMEDIA_STREAM_1SUB(x) media_stream_1sub(XMEDIA_STREAM(x))
312 #define XMEDIA_STREAM_NSUB(x) media_stream_nsub(XMEDIA_STREAM(x))
313
314 \f
315 extern Lisp_Object make_media_stream(void);
316 extern media_substream *make_media_substream(void);
317 extern media_substream *make_media_substream_append(Lisp_Media_Stream*);
318 extern media_substream *make_media_substream_prepend(Lisp_Media_Stream*);
319
320 extern Lisp_Object Q_data, Q_file, Q_url;
321
322 EXFUN(Fmake_media_stream, 3);
323
324 /* A struct for virtual-I/O */
325 struct media_data {
326         size_t length;
327         long seek;
328         char *data;
329 };
330
331 /******************/
332 /* audio coercion */
333 /******************/
334 struct media_sample_format_s {
335         audio_resample_fun upsample;
336         audio_resample_fun downsample;
337 };
338
339 struct audio_coerce_chain_s {
340         audio_coerce_fun fun;
341         audio_coerce_args args;
342         audio_coerce_chain_t *next;
343         audio_coerce_chain_t *last;
344 };
345
346 #define DECLARE_MEDIA_SAMPLE_FORMAT(_name)      \
347         extern media_sample_format_t _name[1]
348 #define DECLARE_MEDIA_SAMPLE_FORMAT_UP(_name)   \
349         static void _name##_up(void*, void*, size_t);
350 #define DECLARE_MEDIA_SAMPLE_FORMAT_DOWN(_name) \
351         static void _name##_down(void*, void*, size_t);
352 #define DECLARE_MEDIA_SAMPLE_FORMAT_SIMPLE(_name)       \
353         DECLARE_MEDIA_SAMPLE_FORMAT_UP(_name);  \
354         DECLARE_MEDIA_SAMPLE_FORMAT_DOWN(_name);
355
356 #define DEFINE_MEDIA_SAMPLE_FORMAT_CUSTOM(_name, _up, _down)            \
357         media_sample_format_t _name[1] = { { (_up), (_down) } }
358 #define DEFINE_MEDIA_SAMPLE_FORMAT(_name, _up, _down)                   \
359         DEFINE_MEDIA_SAMPLE_FORMAT_CUSTOM((_name),                      \
360                                           (_name##_##_up),              \
361                                           (_name##_##_down))
362 #define DEFINE_MEDIA_SAMPLE_FORMAT_SIMPLE(_name)                        \
363         DECLARE_MEDIA_SAMPLE_FORMAT_SIMPLE(_name)                       \
364         DEFINE_MEDIA_SAMPLE_FORMAT(_name, up, down)
365 #define DEFINE_MEDIA_SAMPLE_FORMAT_EMPTY(_name)                         \
366         DEFINE_MEDIA_SAMPLE_FORMAT_CUSTOM((_name), NULL, NULL)
367
368 #define MEDIA_SAMPLE_FORMAT_UPSAMPLE(_msf) (_msf)->upsample
369 #define MEDIA_SAMPLE_FORMAT_DOWNSAMPLE(_msf) (_msf)->downsample
370
371 #define MEDIA_SAMPLE_FORMAT(_msf) (_msf)
372
373
374 /* `effects' */
375 #define DECLARE_MEDIA_SAMPLE_EFFECT(_name, args...)     \
376         extern audio_coerce_fun _name[1];               \
377         typedef struct {                                \
378                         args                            \
379         } _name##_args;
380
381 #define DEFINE_MEDIA_SAMPLE_EFFECT(_name, _fun)         \
382         static size_t _fun(sxe_media_sample_t *,        \
383                            sxe_media_sample_t *,        \
384                            size_t, void *);             \
385         audio_coerce_fun _name[1] = { (_fun) }
386
387 #define MEDIA_SAMPLE_EFFECT(_mse) (_mse)[0]
388
389 #define MEDIA_SAMPLE_VOLUME_NORM 0x7f
390 #define MEDIA_SAMPLE_VOLUME_MAX  0xff
391 #define MEDIA_SAMPLE_VOLUME_MIN  0x00
392 #define MEDIA_MAX_AUDIO_CHANNELS 16 /* maximal number of audio channels */
393
394 #define PUT_MEDIA_SAMPLE_EFFECT(_chain, _idx, _mse, _mse_arg)   \
395         do {                                                    \
396                 (&(_chain[(_idx)]))->fun = (_mse);              \
397                 (&(_chain[(_idx)]))->args = (_mse_arg);         \
398         } while (0)
399 #define ADD_MEDIA_SAMPLE_EFFECT(_chain, _idx, _mse, _mse_arg)           \
400         do {                                                            \
401                 PUT_MEDIA_SAMPLE_EFFECT(_chain, _idx, _mse, _mse_arg);  \
402                 (_idx)++;                                               \
403         } while (0)
404 #define GET_MEDIA_SAMPLE_EFFECT_FUN(_chain, _idx)                       \
405         (&(_chain[(_idx)]))->fun
406 #define GET_MEDIA_SAMPLE_EFFECT_ARGS(_chain, _idx)                      \
407         (&(_chain[(_idx)]))->args
408 #define CALL_MEDIA_SAMPLE_EFFECT(_chain, _idx, _dst, _src, _len)        \
409         GET_MEDIA_SAMPLE_EFFECT_FUN(_chain, _idx)(                      \
410                 (_dst), (_src), (_len),                                 \
411                 GET_MEDIA_SAMPLE_EFFECT_ARGS(_chain, _idx))
412
413 /* some predefined sample formats */
414 DECLARE_MEDIA_SAMPLE_FORMAT(sxe_msf_U8);
415 DECLARE_MEDIA_SAMPLE_FORMAT(sxe_msf_S16);
416 DECLARE_MEDIA_SAMPLE_FORMAT(sxe_msf_FLT);
417 DECLARE_MEDIA_SAMPLE_FORMAT(sxe_msf_S32);
418 DECLARE_MEDIA_SAMPLE_FORMAT(sxe_msf_S24); /* format internally used */
419
420 /* some predefined effects */
421 DECLARE_MEDIA_SAMPLE_EFFECT(sxe_mse_1ch_to_2ch);
422 DECLARE_MEDIA_SAMPLE_EFFECT(sxe_mse_2ch_to_1ch,
423                             int chan;); /* which channel to keep */
424 DECLARE_MEDIA_SAMPLE_EFFECT(sxe_mse_5ch_to_2ch,
425                             int chan1;
426                             int chan2;);
427 DECLARE_MEDIA_SAMPLE_EFFECT(sxe_mse_volume,
428                             int num_channels;
429                             uint8_t volume[MEDIA_MAX_AUDIO_CHANNELS];);
430 DECLARE_MEDIA_SAMPLE_EFFECT(sxe_mse_rerate,
431                             size_t srcrate;
432                             size_t tgtrate;
433                             float tweak;
434                             int num_channels;);
435
436 #define SXE_MAX_S32  2147483647.0f
437 #define SXE_MAX_S24  8388607.0f
438 #define SXE_MAX_S16  32767.0f
439 #define SXE_MAX_S8   127.0f
440 #define SXE_MAX_U8   255.0f
441
442 #define MEDIA_MAX_AUDIO_FRAME_SIZE 384000 /* 2 secs of 48kHz, 32bit, stereo */
443
444 #ifdef ALL_DEBUG_FLAGS
445 #undef MEDIA_DEBUG_FLAG
446 #define MEDIA_DEBUG_FLAG
447 #endif
448
449 #define __MEDIA_DEBUG__(args...)        fprintf(stderr, "MEDIA " args)
450 #ifndef MEDIA_DEBUG_FLAG
451 #define MEDIA_DEBUG(args...)
452 #else
453 #define MEDIA_DEBUG(args...)            __MEDIA_DEBUG__(args)
454 #endif
455 #define MEDIA_DEBUG_FMT(args...)        MEDIA_DEBUG("[format] " args)
456 #define MEDIA_DEBUG_COE(args...)        MEDIA_DEBUG("[coerce] " args)
457 #define MEDIA_CRITICAL(args...)         __MEDIA_DEBUG__("CRITICAL: " args)
458
459 #endif  /* INCLUDED_media_h_ */