DOSBox-X
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines
src/aviwriter/riff.h
00001 /*
00002  *  Copyright (C) 2018-2020 Jon Campbell
00003  *
00004  *  This program is free software; you can redistribute it and/or modify
00005  *  it under the terms of the GNU General Public License as published by
00006  *  the Free Software Foundation; either version 2 of the License, or
00007  *  (at your option) any later version.
00008  *
00009  *  This program is distributed in the hope that it will be useful,
00010  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  *  GNU General Public License for more details.
00013  *
00014  *  You should have received a copy of the GNU General Public License along
00015  *  with this program; if not, write to the Free Software Foundation, Inc.,
00016  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017  */
00018 
00019 #ifndef __VIDEOMGRUTIL_RIFF_H
00020 #define __VIDEOMGRUTIL_RIFF_H
00021 
00022 #include <stdint.h>
00023 #include <string.h>
00024 #include <stdio.h>
00025 
00026 #include "informational.h"
00027 
00028 typedef uint32_t riff_fourcc_t;
00029 #define riff_fourcc_const(a,b,c,d)      ( (((uint32_t)(a)) << 0U) | (((uint32_t)(b)) << 8U) | (((uint32_t)(c)) << 16U) | (((uint32_t)(d)) << 24U) )
00030 
00031 #define riff_LIST               riff_fourcc_const('L','I','S','T')
00032 #define riff_RIFF               riff_fourcc_const('R','I','F','F')
00033 
00034 #define riff_wav_fmt            riff_fourcc_const('f','m','t',' ')
00035 #define riff_wav_data           riff_fourcc_const('d','a','t','a')
00036 
00037 typedef struct {
00038         int64_t                 absolute_header_offset;
00039         int64_t                 absolute_data_offset;
00040         int64_t                 absolute_offset_next_chunk;
00041         riff_fourcc_t           fourcc;
00042         uint32_t                data_length;
00043         uint32_t                absolute_data_length;
00044         riff_fourcc_t           list_fourcc;
00045         int64_t                 read_offset;
00046         int64_t                 write_offset;
00047         int                     wmode;
00048         unsigned char           disable_sync;           /* 1=riff_stack_pop() will NOT rewrite the header.
00049                                                            caller would use this if using riff_stack_streamwrite()
00050                                                            to blast the data to disk as fast as possible */
00051         unsigned char           placeholder;            /* 1=write 0xFFFFFFFF as a placeholder for the actual size
00052                                                            until the header is actually updated. you should really
00053                                                            only set this flag for LIST chunks that are unlikely to
00054                                                            be zero bytes in length. flag is cleared automatically
00055                                                            by riff_stack_pop(). do NOT set if disable_sync is set. */
00056 } riff_chunk;
00057 
00058 static const riff_chunk RIFF_CHUNK_INIT = {
00059         0,
00060         0,
00061         0,
00062         0,
00063         0,
00064         0,
00065         0,
00066         0,
00067         0,
00068         0,
00069         0,
00070         0
00071 };
00072 
00073 typedef struct {
00074         int                     current,depth;
00075         riff_chunk              *stack,*top;
00076 
00077         int                     fd;
00078         int                     eof;
00079         void*                   user;
00080         int                     wmode;
00081         int64_t                 next_read;
00082         int64_t                 next_write;
00083         void*                   buffer;
00084         size_t                  buflen;
00085         size_t                  bufofs;
00086         int                     (*read)(void *a,void *b,size_t c);
00087         int64_t                 (*seek)(void *a,int64_t offset);
00088         int                     (*write)(void *a,const void *b,size_t c);
00089 
00090         /* flags for controlling some of the optimizations used in this code */
00091         unsigned char           always_lseek;           /* 1=always lseek()
00092                                                            0=ignore lseek() if file pointer should be at that point anyway
00093                                                            EXPLANATION: Linux disk I/O caching is more likely to provide better
00094                                                                         throughput if we avoid lseek() and write structures and
00095                                                                         data using only a continuous series of read() or write()
00096                                                                         calls. */
00097 
00098         /* variables provided for the file I/O code */
00099         int64_t                 trk_file_pointer;
00100 
00101         /* more flags */
00102         unsigned int            fd_owner:1;             /* if set, we take ownership of the file descriptor */
00103 } riff_stack;
00104 
00105 int riff_std_read(void *a,void *b,size_t c);
00106 int riff_std_write(void *a,const void *b,size_t c);
00107 int64_t riff_std_seek(void *a,int64_t offset);
00108 
00109 riff_stack *riff_stack_create(int depth);
00110 riff_stack *riff_stack_destroy(riff_stack *s);
00111 int riff_stack_is_empty(riff_stack *s);
00112 int riff_stack_empty(riff_stack *s);
00113 riff_chunk *riff_stack_top(riff_stack *s);
00114 riff_chunk *riff_stack_pop(riff_stack *s);
00115 int riff_stack_push(riff_stack *s,riff_chunk *c);
00116 int64_t riff_stack_seek(riff_stack *s,riff_chunk *c,int64_t of);
00117 int riff_stack_read(riff_stack *s,riff_chunk *c,void *buf,size_t len);
00118 int riff_stack_write(riff_stack *s,riff_chunk *c,const void *buf,size_t len);
00119 int riff_stack_streamwrite(riff_stack *s,riff_chunk *c,const void *buf,size_t len);
00120 int64_t riff_stack_current_chunk_offset(riff_stack *s);
00121 int riff_stack_assign_fd(riff_stack *s,int fd);
00122 int riff_stack_assign_fd_ownership(riff_stack *s);
00123 int riff_stack_assign_buffer(riff_stack *s,void *buffer,size_t len);
00124 int riff_stack_chunk_contains_subchunks(riff_chunk *c);
00125 int riff_stack_readchunk(riff_stack *s,riff_chunk *pc,riff_chunk *c);
00126 int riff_stack_set_chunk_data_type(riff_chunk *c,riff_fourcc_t fcc);
00127 int riff_stack_set_chunk_list_type(riff_chunk *c,riff_fourcc_t list,riff_fourcc_t fcc);
00128 void riff_stack_debug_chunk_dump(FILE *fp,riff_stack *riff,riff_chunk *chunk);
00129 void riff_stack_debug_print(FILE *fp,int level,riff_chunk *chunk);
00130 void riff_chunk_improvise(riff_chunk *c,uint64_t ofs,uint32_t size);
00131 void riff_stack_fourcc_to_str(riff_fourcc_t t,char *tmp);
00132 void riff_stack_debug_print_indent(FILE *fp,int level);
00133 int riff_stack_eof(riff_stack *r);
00134 int riff_stack_prepare_for_writing(riff_stack *r,int wmode);
00135 int riff_stack_begin_new_chunk_here(riff_stack *s,riff_chunk *c);
00136 int riff_stack_header_sync(riff_stack *s,riff_chunk *c);
00137 int riff_stack_header_sync_all(riff_stack *s);
00138 int riff_stack_chunk_limit(riff_stack *s,int len);
00139 int riff_stack_enable_placeholder(riff_stack *s,riff_chunk *c);
00140 void riff_stack_writing_sync(riff_stack *s);
00141 
00142 #define RIFF_CHUNK_HEADER_LENGTH                8
00143 #define RIFF_LIST_CHUNK_HEADER_LENGTH           12
00144 
00145 #endif
00146