3 * author: Tahseen Mohammad
14 /* write an ogg_page to a file pointer */
15 int write_ogg_page_to_file(ogg_page
*og
, FILE *out
) {
18 written
= fwrite(og
->header
,1, og
->header_len
, out
);
19 written
+= fwrite(og
->body
,1, og
->body_len
, out
);
24 int add_message_header_field(fisbone_packet
*fp
,
28 /* size of both key and value + ': ' + CRLF */
29 int this_message_size
= strlen(header_key
) + strlen(header_value
) + 4;
30 if (fp
->message_header_fields
== NULL
) {
31 fp
->message_header_fields
= _ogg_calloc(this_message_size
, sizeof(char));
33 int new_size
= (fp
->current_header_size
+ this_message_size
) * sizeof(char);
34 fp
->message_header_fields
= _ogg_realloc(fp
->message_header_fields
, new_size
);
36 snprintf(fp
->message_header_fields
+ fp
->current_header_size
,
41 fp
->current_header_size
+= this_message_size
;
46 /* create a ogg_packet from a fishead_packet structure */
47 ogg_packet
ogg_from_fishead(fishead_packet
*fp
) {
51 memset(&op
, 0, sizeof(op
));
52 op
.packet
= _ogg_calloc(FISHEAD_SIZE
, sizeof(unsigned char));
53 memset(op
.packet
, 0, FISHEAD_SIZE
);
55 memcpy (op
.packet
, FISHEAD_IDENTIFIER
, 8); /* identifier */
56 *((ogg_uint16_t
*)(op
.packet
+8)) = SKELETON_VERSION_MAJOR
; /* version major */
57 *((ogg_uint16_t
*)(op
.packet
+10)) = SKELETON_VERSION_MINOR
; /* version minor */
58 *((ogg_int64_t
*)(op
.packet
+12)) = (ogg_int64_t
)fp
->ptime_n
; /* presentationtime numerator */
59 *((ogg_int64_t
*)(op
.packet
+20)) = (ogg_int64_t
)fp
->ptime_d
; /* presentationtime denominator */
60 *((ogg_int64_t
*)(op
.packet
+28)) = (ogg_int64_t
)fp
->btime_n
; /* basetime numerator */
61 *((ogg_int64_t
*)(op
.packet
+36)) = (ogg_int64_t
)fp
->btime_d
; /* basetime denominator */
62 /* TODO: UTC time, set to zero for now */
64 op
.b_o_s
= 1; /* its the first packet of the stream */
65 op
.e_o_s
= 0; /* its not the last packet of the stream */
66 op
.bytes
= FISHEAD_SIZE
; /* length of the packet in bytes */
71 /* create a ogg_packet from a fisbone_packet structure.
72 * call this method after the fisbone_packet is filled and all message header fields are added
73 * by calling add_message_header_field method.
75 ogg_packet
ogg_from_fisbone(fisbone_packet
*fp
) {
78 int packet_size
= FISBONE_SIZE
+ fp
->current_header_size
;
80 memset (&op
, 0, sizeof (op
));
81 op
.packet
= _ogg_calloc (packet_size
, sizeof(unsigned char));
82 memset (op
.packet
, 0, packet_size
);
83 memcpy (op
.packet
, FISBONE_IDENTIFIER
, 8); /* identifier */
84 *((ogg_uint32_t
*)(op
.packet
+8)) = FISBONE_MESSAGE_HEADER_OFFSET
; /* offset of the message header fields */
85 *((ogg_uint32_t
*)(op
.packet
+12)) = fp
->serial_no
; /* serialno of the respective stream */
86 *((ogg_uint32_t
*)(op
.packet
+16)) = fp
->nr_header_packet
; /* number of header packets */
87 *((ogg_int64_t
*)(op
.packet
+20)) = fp
->granule_rate_n
; /* granulrate numerator */
88 *((ogg_int64_t
*)(op
.packet
+28)) = fp
->granule_rate_d
; /* granulrate denominator */
89 *((ogg_int64_t
*)(op
.packet
+36)) = fp
->start_granule
; /* start granule */
90 *((ogg_uint32_t
*)(op
.packet
+44)) = fp
->preroll
; /* preroll, for theora its 0 */
91 *(op
.packet
+48) = fp
->granule_shift
; /* granule shift */
92 memcpy((op
.packet
+FISBONE_SIZE
), fp
->message_header_fields
, fp
->current_header_size
);
96 op
.bytes
= packet_size
; /* size of the packet in bytes */
101 /* fills up a fishead_packet from a fishead ogg_packet of a skeleton bistream */
102 fishead_packet
fishead_from_ogg(ogg_packet
*op
) {
106 if (memcmp(op
->packet
, FISHEAD_IDENTIFIER
, 8))
107 ; /* invalid packet what do we do? */
109 fp
.version_major
= *((ogg_uint16_t
*)(op
->packet
+8)); /* version major */
110 fp
.version_minor
= *((ogg_uint16_t
*)(op
->packet
+10)); /* version minor */
111 fp
.ptime_n
= *((ogg_int64_t
*)(op
->packet
+12)); /* presentationtime numerator */
112 fp
.ptime_d
= *((ogg_int64_t
*)(op
->packet
+20)); /* presentationtime denominator */
113 fp
.btime_n
= *((ogg_int64_t
*)(op
->packet
+28)); /* basetime numerator */
114 fp
.btime_d
= *((ogg_int64_t
*)(op
->packet
+36)); /* basetime denominator */
115 memcpy(fp
.UTC
, op
->packet
+44, 20);
120 /* fills up a fisbone_packet from a fisbone ogg_packet of a skeleton bitstream */
121 fisbone_packet
fisbone_from_ogg(ogg_packet
*op
) {
125 if (memcmp(op
->packet
, FISBONE_IDENTIFIER
, 8))
126 ; /* invalid value, what do we do? */
127 fp
.serial_no
= *((ogg_uint32_t
*)(op
->packet
+12)); /* serialno of the stream represented by this fisbone packet */
128 fp
.nr_header_packet
= *((ogg_uint32_t
*)(op
->packet
+16)); /* number of header packets */
129 fp
.granule_rate_n
= *((ogg_int64_t
*)(op
->packet
+20)); /* granulrate numerator */
130 fp
.granule_rate_d
= *((ogg_int64_t
*)(op
->packet
+28)); /* granulrate denominator */
131 fp
.start_granule
= *((ogg_int64_t
*)(op
->packet
+36)); /* start granule */
132 fp
.preroll
= *((ogg_uint32_t
*)(op
->packet
+44)); /* preroll, for theora its 0 */
133 fp
.granule_shift
= *(op
->packet
+48); /* granule shift */
134 fp
.current_header_size
= op
->bytes
- FISBONE_SIZE
;
135 fp
.message_header_fields
= _ogg_calloc(fp
.current_header_size
+1, sizeof(char));
136 memcpy(fp
.message_header_fields
, op
->packet
+FISBONE_SIZE
, fp
.current_header_size
);
141 int add_fishead_to_stream(ogg_stream_state
*os
, fishead_packet
*fp
) {
145 op
= ogg_from_fishead(fp
);
146 ogg_stream_packetin(os
, &op
);
147 _ogg_free(op
.packet
);
152 int add_fisbone_to_stream(ogg_stream_state
*os
, fisbone_packet
*fp
) {
156 op
= ogg_from_fisbone(fp
);
157 ogg_stream_packetin(os
, &op
);
158 _ogg_free(op
.packet
);
163 int add_eos_packet_to_stream(ogg_stream_state
*os
) {
167 memset (&op
, 0, sizeof(op
));
169 ogg_stream_packetin(os
, &op
);
174 int flush_ogg_stream_to_file(ogg_stream_state
*os
, FILE *out
) {
179 while((result
= ogg_stream_flush(os
, &og
)))
182 result
= write_ogg_page_to_file(&og
, out
);
183 if(result
!= og
.header_len
+ og
.body_len
)