]> 4ch.mooo.com Git - 16.git/blob - src/lib/dl/ext/vorbtool/skeleton.c
refresh wwww
[16.git] / src / lib / dl / ext / vorbtool / skeleton.c
1 /*
2  * skeleton.c
3  * author: Tahseen Mohammad
4  */
5
6 /* This file depends on WORDS_BIGENDIAN being defined to 1 if the host
7  * processor stores words with the most significant byte first (like Motorola
8  * and SPARC, unlike Intel and VAX).
9  * On little endian systems, WORDS_BIGENDIAN should be undefined.
10  *
11  * When using GNU Autotools, the correct value will be written into config.h
12  * if the autoconf macro AC_C_BIGENDIAN is called in configure.ac.
13  */
14 #include "config.h"
15
16 #include <stdlib.h>
17 #include <string.h>
18 #include <stdio.h>
19
20 #include <ext/libogg/ogg.h>
21
22 #include "skeleton.h"
23
24 #ifdef WIN32
25 #define snprintf _snprintf
26 #endif
27
28 extern int oe_write_page(ogg_page *page, FILE *fp);
29
30 static  unsigned short
31 _le_16 (unsigned short s)
32 {
33   unsigned short ret=s;
34 #ifdef WORDS_BIGENDIAN
35   ret = (s>>8) & 0x00ffU;
36   ret += (s<<8) & 0xff00U;
37 #endif
38   return ret;
39 }
40
41 static  ogg_uint32_t
42 _le_32 (ogg_uint32_t i)
43 {
44    ogg_uint32_t ret=i;
45 #ifdef WORDS_BIGENDIAN
46    ret =  (i>>24);
47    ret += (i>>8) & 0x0000ff00;
48    ret += (i<<8) & 0x00ff0000;
49    ret += (i<<24);
50 #endif
51    return ret;
52 }
53
54 static  ogg_int64_t
55 _le_64 (ogg_int64_t l)
56 {
57   ogg_int64_t ret=l;
58   unsigned char *ucptr = (unsigned char *)&ret;
59 #ifdef WORDS_BIGENDIAN
60   unsigned char temp;
61
62   temp = ucptr [0] ;
63   ucptr [0] = ucptr [7] ;
64   ucptr [7] = temp ;
65
66   temp = ucptr [1] ;
67   ucptr [1] = ucptr [6] ;
68   ucptr [6] = temp ;
69
70   temp = ucptr [2] ;
71   ucptr [2] = ucptr [5] ;
72   ucptr [5] = temp ;
73
74   temp = ucptr [3] ;
75   ucptr [3] = ucptr [4] ;
76   ucptr [4] = temp ;
77
78 #endif
79   return (*(ogg_int64_t *)ucptr);
80 }
81
82 int add_message_header_field(fisbone_packet *fp, 
83                                         char *header_key, 
84                                         char *header_value) {
85
86     /* size of both key and value + ': ' + CRLF */
87     int this_message_size = strlen(header_key) + strlen(header_value) + 4;
88     if (fp->message_header_fields == NULL) {
89         fp->message_header_fields = _ogg_calloc(this_message_size+1, sizeof(char));
90     } else {
91         int new_size = (fp->current_header_size + this_message_size+1) * sizeof(char);
92         fp->message_header_fields = _ogg_realloc(fp->message_header_fields, new_size);
93     }
94     snprintf(fp->message_header_fields + fp->current_header_size, 
95                 this_message_size+1, 
96                 "%s: %s\r\n", 
97                 header_key, 
98                 header_value);
99     fp->current_header_size += this_message_size;
100
101     return 0;
102 }
103
104 /* create a ogg_packet from a fishead_packet structure */
105 int ogg_from_fishead(fishead_packet *fp,ogg_packet *op) {
106
107     if (!fp || !op) return -1;
108
109     memset(op, 0, sizeof(*op));
110     op->packet = _ogg_calloc(FISHEAD_SIZE, sizeof(unsigned char));
111     if (!op->packet) return -1;
112
113     memset(op->packet, 0, FISHEAD_SIZE);
114
115     memcpy (op->packet, FISHEAD_IDENTIFIER, 8); /* identifier */
116     *((ogg_uint16_t*)(op->packet+8)) = _le_16 (SKELETON_VERSION_MAJOR); /* version major */
117     *((ogg_uint16_t*)(op->packet+10)) = _le_16 (SKELETON_VERSION_MINOR); /* version minor */
118     *((ogg_int64_t*)(op->packet+12)) = _le_64 (fp->ptime_n); /* presentationtime numerator */
119     *((ogg_int64_t*)(op->packet+20)) = _le_64 (fp->ptime_d); /* presentationtime denominator */
120     *((ogg_int64_t*)(op->packet+28)) = _le_64 (fp->btime_n); /* basetime numerator */
121     *((ogg_int64_t*)(op->packet+36)) = _le_64 (fp->btime_d); /* basetime denominator */
122     /* TODO: UTC time, set to zero for now */
123
124     op->b_o_s = 1;   /* its the first packet of the stream */
125     op->e_o_s = 0;   /* its not the last packet of the stream */
126     op->bytes = FISHEAD_SIZE;  /* length of the packet in bytes */
127
128     return 0;
129 }
130
131 /* create a ogg_packet from a fisbone_packet structure. 
132  * call this method after the fisbone_packet is filled and all message header fields are added
133  * by calling add_message_header_field method.
134  */
135 int ogg_from_fisbone(fisbone_packet *fp,ogg_packet *op) {
136
137     int packet_size;
138
139     if (!fp || !op) return -1;
140
141     packet_size = FISBONE_SIZE + fp->current_header_size;
142
143     memset (op, 0, sizeof (*op));
144     op->packet = _ogg_calloc (packet_size, sizeof(unsigned char));
145     if (!op->packet) return -1;
146
147     memset (op->packet, 0, packet_size);
148     memcpy (op->packet, FISBONE_IDENTIFIER, 8); /* identifier */
149     *((ogg_uint32_t*)(op->packet+8)) = _le_32 (FISBONE_MESSAGE_HEADER_OFFSET); /* offset of the message header fields */
150     *((ogg_uint32_t*)(op->packet+12)) = _le_32 (fp->serial_no); /* serialno of the respective stream */
151     *((ogg_uint32_t*)(op->packet+16)) = _le_32 (fp->nr_header_packet); /* number of header packets */
152     *((ogg_int64_t*)(op->packet+20)) = _le_64 (fp->granule_rate_n); /* granulrate numerator */
153     *((ogg_int64_t*)(op->packet+28)) = _le_64 (fp->granule_rate_d); /* granulrate denominator */
154     *((ogg_int64_t*)(op->packet+36)) = _le_64 (fp->start_granule); /* start granule */
155     *((ogg_uint32_t*)(op->packet+44)) = _le_32 (fp->preroll); /* preroll, for theora its 0 */
156     *(op->packet+48) = fp->granule_shift; /* granule shift */
157     memcpy((op->packet+FISBONE_SIZE), fp->message_header_fields, fp->current_header_size);
158
159     op->b_o_s = 0;
160     op->e_o_s = 0;
161     op->bytes = packet_size; /* size of the packet in bytes */
162
163     return 0;
164 }
165
166 int add_fishead_to_stream(ogg_stream_state *os, fishead_packet *fp) {
167
168     ogg_packet op;
169     int ret;
170
171     ret = ogg_from_fishead(fp, &op);
172     if (ret<0) return ret;
173     ogg_stream_packetin(os, &op);
174     _ogg_free(op.packet);
175
176     return 0;
177 }
178
179 int add_fisbone_to_stream(ogg_stream_state *os, fisbone_packet *fp) {
180
181     ogg_packet op;
182     int ret;
183
184     ret = ogg_from_fisbone(fp, &op);
185     if (ret<0) return ret;
186     ogg_stream_packetin(os, &op);
187     _ogg_free(op.packet);
188
189     return 0;
190 }
191
192 int add_eos_packet_to_stream(ogg_stream_state *os) {
193
194     ogg_packet op;
195
196     memset (&op, 0, sizeof(op));
197     op.e_o_s = 1;
198
199     return ogg_stream_packetin(os, &op);
200 }
201
202 int flush_ogg_stream_to_file(ogg_stream_state *os, FILE *out) {
203
204     ogg_page og;
205     int result;
206
207     while((result = ogg_stream_flush(os, &og))) {
208         if(!result) break;
209         result = oe_write_page(&og, out);
210         if(result != og.header_len + og.body_len)
211             return 1;
212     }
213
214     return 0;
215 }