3 * author: Tahseen Mohammad
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.
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.
25 #define snprintf _snprintf
28 extern int oe_write_page(ogg_page
*page
, FILE *fp
);
31 _le_16 (unsigned short s
)
34 #ifdef WORDS_BIGENDIAN
35 ret
= (s
>>8) & 0x00ffU
;
36 ret
+= (s
<<8) & 0xff00U
;
42 _le_32 (ogg_uint32_t i
)
45 #ifdef WORDS_BIGENDIAN
47 ret
+= (i
>>8) & 0x0000ff00;
48 ret
+= (i
<<8) & 0x00ff0000;
55 _le_64 (ogg_int64_t l
)
58 unsigned char *ucptr
= (unsigned char *)&ret
;
59 #ifdef WORDS_BIGENDIAN
63 ucptr
[0] = ucptr
[7] ;
67 ucptr
[1] = ucptr
[6] ;
71 ucptr
[2] = ucptr
[5] ;
75 ucptr
[3] = ucptr
[4] ;
79 return (*(ogg_int64_t
*)ucptr
);
82 int add_message_header_field(fisbone_packet
*fp
,
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));
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
);
94 snprintf(fp
->message_header_fields
+ fp
->current_header_size
,
99 fp
->current_header_size
+= this_message_size
;
104 /* create a ogg_packet from a fishead_packet structure */
105 int ogg_from_fishead(fishead_packet
*fp
,ogg_packet
*op
) {
107 if (!fp
|| !op
) return -1;
109 memset(op
, 0, sizeof(*op
));
110 op
->packet
= _ogg_calloc(FISHEAD_SIZE
, sizeof(unsigned char));
111 if (!op
->packet
) return -1;
113 memset(op
->packet
, 0, FISHEAD_SIZE
);
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 */
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 */
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.
135 int ogg_from_fisbone(fisbone_packet
*fp
,ogg_packet
*op
) {
139 if (!fp
|| !op
) return -1;
141 packet_size
= FISBONE_SIZE
+ fp
->current_header_size
;
143 memset (op
, 0, sizeof (*op
));
144 op
->packet
= _ogg_calloc (packet_size
, sizeof(unsigned char));
145 if (!op
->packet
) return -1;
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
);
161 op
->bytes
= packet_size
; /* size of the packet in bytes */
166 int add_fishead_to_stream(ogg_stream_state
*os
, fishead_packet
*fp
) {
171 ret
= ogg_from_fishead(fp
, &op
);
172 if (ret
<0) return ret
;
173 ogg_stream_packetin(os
, &op
);
174 _ogg_free(op
.packet
);
179 int add_fisbone_to_stream(ogg_stream_state
*os
, fisbone_packet
*fp
) {
184 ret
= ogg_from_fisbone(fp
, &op
);
185 if (ret
<0) return ret
;
186 ogg_stream_packetin(os
, &op
);
187 _ogg_free(op
.packet
);
192 int add_eos_packet_to_stream(ogg_stream_state
*os
) {
196 memset (&op
, 0, sizeof(op
));
199 return ogg_stream_packetin(os
, &op
);
202 int flush_ogg_stream_to_file(ogg_stream_state
*os
, FILE *out
) {
207 while((result
= ogg_stream_flush(os
, &og
))) {
209 result
= oe_write_page(&og
, out
);
210 if(result
!= og
.header_len
+ og
.body_len
)