Mercurial > libavformat.hg
annotate ogg.c @ 404:6579fe3ade40 libavformat
remove spyware from ogg*.c
fix vorbis in ogg decoding
author | michael |
---|---|
date | Sun, 04 Apr 2004 01:10:50 +0000 |
parents | 741c56c608bb |
children | 04d7dda7ccd5 |
rev | line source |
---|---|
0 | 1 /* |
2 * Ogg bitstream support | |
3 * Mark Hills <mark@pogo.org.uk> | |
4 * | |
5 * Uses libogg, but requires libvorbisenc to construct correct headers | |
6 * when containing Vorbis stream -- currently the only format supported | |
7 */ | |
8 | |
9 #include <stdio.h> | |
10 | |
11 #include <ogg/ogg.h> | |
12 #include <vorbis/vorbisenc.h> | |
13 | |
14 #include "avformat.h" | |
15 #include "oggvorbis.h" | |
16 | |
17 #define DECODER_BUFFER_SIZE 4096 | |
18 | |
19 | |
20 typedef struct OggContext { | |
21 /* output */ | |
22 ogg_stream_state os ; | |
23 int header_handled ; | |
24 ogg_int64_t base_packet_no ; | |
25 ogg_int64_t base_granule_pos ; | |
26 | |
27 /* input */ | |
28 ogg_sync_state oy ; | |
29 } OggContext ; | |
30 | |
31 | |
277
a313e1080322
disable encoders where appropriate (patch courtesy of BERO
melanson
parents:
68
diff
changeset
|
32 #ifdef CONFIG_ENCODERS |
35 | 33 static int ogg_write_header(AVFormatContext *avfcontext) |
34 { | |
35 OggContext *context = avfcontext->priv_data; | |
0 | 36 AVCodecContext *avccontext ; |
37 vorbis_info vi ; | |
38 vorbis_dsp_state vd ; | |
39 vorbis_comment vc ; | |
40 vorbis_block vb ; | |
41 ogg_packet header, header_comm, header_code ; | |
42 int n ; | |
43 | |
404 | 44 ogg_stream_init(&context->os, 31415); |
0 | 45 |
46 for(n = 0 ; n < avfcontext->nb_streams ; n++) { | |
47 avccontext = &avfcontext->streams[n]->codec ; | |
48 | |
49 /* begin vorbis specific code */ | |
50 | |
51 vorbis_info_init(&vi) ; | |
52 | |
53 /* code copied from libavcodec/oggvorbis.c */ | |
54 | |
55 if(oggvorbis_init_encoder(&vi, avccontext) < 0) { | |
56 fprintf(stderr, "ogg_write_header: init_encoder failed") ; | |
57 return -1 ; | |
58 } | |
59 | |
60 vorbis_analysis_init(&vd, &vi) ; | |
61 vorbis_block_init(&vd, &vb) ; | |
62 | |
63 vorbis_comment_init(&vc) ; | |
327 | 64 vorbis_comment_add_tag(&vc, "encoder", LIBAVFORMAT_IDENT) ; |
0 | 65 if(*avfcontext->title) |
66 vorbis_comment_add_tag(&vc, "title", avfcontext->title) ; | |
67 | |
68 vorbis_analysis_headerout(&vd, &vc, &header, | |
69 &header_comm, &header_code) ; | |
70 ogg_stream_packetin(&context->os, &header) ; | |
71 ogg_stream_packetin(&context->os, &header_comm) ; | |
72 ogg_stream_packetin(&context->os, &header_code) ; | |
73 | |
68
1e2f55eced38
ogg deallocate patch by (Mark Hills <mark at pogo dot org dot uk>)
michaelni
parents:
35
diff
changeset
|
74 vorbis_block_clear(&vb) ; |
1e2f55eced38
ogg deallocate patch by (Mark Hills <mark at pogo dot org dot uk>)
michaelni
parents:
35
diff
changeset
|
75 vorbis_dsp_clear(&vd) ; |
1e2f55eced38
ogg deallocate patch by (Mark Hills <mark at pogo dot org dot uk>)
michaelni
parents:
35
diff
changeset
|
76 vorbis_info_clear(&vi) ; |
0 | 77 vorbis_comment_clear(&vc) ; |
68
1e2f55eced38
ogg deallocate patch by (Mark Hills <mark at pogo dot org dot uk>)
michaelni
parents:
35
diff
changeset
|
78 |
0 | 79 /* end of vorbis specific code */ |
80 | |
81 context->header_handled = 0 ; | |
82 context->base_packet_no = 0 ; | |
83 } | |
84 | |
85 return 0 ; | |
86 } | |
87 | |
88 | |
89 static int ogg_write_packet(AVFormatContext *avfcontext, | |
90 int stream_index, | |
290
7a3ed84008ec
GCC 3.3.2 warnings patch by (Panagiotis Issaris <takis at lumumba dot luc dot ac dot be>)
michael
parents:
277
diff
changeset
|
91 const uint8_t *buf, int size, int64_t force_pts) |
0 | 92 { |
93 OggContext *context = avfcontext->priv_data ; | |
94 ogg_packet *op ; | |
95 ogg_page og ; | |
96 int l = 0 ; | |
97 | |
98 /* flush header packets so audio starts on a new page */ | |
99 | |
100 if(!context->header_handled) { | |
101 while(ogg_stream_flush(&context->os, &og)) { | |
102 put_buffer(&avfcontext->pb, og.header, og.header_len) ; | |
103 put_buffer(&avfcontext->pb, og.body, og.body_len) ; | |
104 put_flush_packet(&avfcontext->pb); | |
105 } | |
106 context->header_handled = 1 ; | |
107 } | |
108 | |
109 while(l < size) { | |
110 op = (ogg_packet*)(buf + l) ; | |
290
7a3ed84008ec
GCC 3.3.2 warnings patch by (Panagiotis Issaris <takis at lumumba dot luc dot ac dot be>)
michael
parents:
277
diff
changeset
|
111 op->packet = (uint8_t*) buf + l + sizeof( ogg_packet) ; /* fix data pointer */ |
0 | 112 |
113 if(!context->base_packet_no) { /* this is the first packet */ | |
114 context->base_packet_no = op->packetno ; | |
115 context->base_granule_pos = op->granulepos ; | |
116 } | |
117 | |
118 /* correct the fields in the packet -- essential for streaming */ | |
119 | |
120 op->packetno -= context->base_packet_no ; | |
121 op->granulepos -= context->base_granule_pos ; | |
122 | |
123 ogg_stream_packetin(&context->os, op) ; | |
124 l += sizeof(ogg_packet) + op->bytes ; | |
125 | |
126 while(ogg_stream_pageout(&context->os, &og)) { | |
127 put_buffer(&avfcontext->pb, og.header, og.header_len) ; | |
128 put_buffer(&avfcontext->pb, og.body, og.body_len) ; | |
129 put_flush_packet(&avfcontext->pb); | |
130 } | |
131 } | |
132 | |
133 return 0; | |
134 } | |
135 | |
136 | |
137 static int ogg_write_trailer(AVFormatContext *avfcontext) { | |
138 OggContext *context = avfcontext->priv_data ; | |
139 ogg_page og ; | |
140 | |
141 while(ogg_stream_flush(&context->os, &og)) { | |
142 put_buffer(&avfcontext->pb, og.header, og.header_len) ; | |
143 put_buffer(&avfcontext->pb, og.body, og.body_len) ; | |
144 put_flush_packet(&avfcontext->pb); | |
145 } | |
146 | |
147 ogg_stream_clear(&context->os) ; | |
148 return 0 ; | |
149 } | |
150 | |
151 | |
152 static AVOutputFormat ogg_oformat = { | |
153 "ogg", | |
154 "Ogg Vorbis", | |
155 "audio/x-vorbis", | |
156 "ogg", | |
157 sizeof(OggContext), | |
158 CODEC_ID_VORBIS, | |
159 0, | |
160 ogg_write_header, | |
161 ogg_write_packet, | |
162 ogg_write_trailer, | |
163 } ; | |
277
a313e1080322
disable encoders where appropriate (patch courtesy of BERO
melanson
parents:
68
diff
changeset
|
164 #endif //CONFIG_ENCODERS |
0 | 165 |
166 | |
167 static int next_packet(AVFormatContext *avfcontext, ogg_packet *op) { | |
168 OggContext *context = avfcontext->priv_data ; | |
169 ogg_page og ; | |
170 char *buf ; | |
171 | |
172 while(ogg_stream_packetout(&context->os, op) != 1) { | |
173 | |
174 /* while no pages are available, read in more data to the sync */ | |
175 while(ogg_sync_pageout(&context->oy, &og) != 1) { | |
176 buf = ogg_sync_buffer(&context->oy, DECODER_BUFFER_SIZE) ; | |
177 if(get_buffer(&avfcontext->pb, buf, DECODER_BUFFER_SIZE) <= 0) | |
178 return 1 ; | |
179 ogg_sync_wrote(&context->oy, DECODER_BUFFER_SIZE) ; | |
180 } | |
181 | |
182 /* got a page. Feed it into the stream and get the packet */ | |
183 if(ogg_stream_pagein(&context->os, &og) != 0) | |
184 return 1 ; | |
185 } | |
186 | |
187 return 0 ; | |
188 } | |
189 | |
190 | |
191 static int ogg_read_header(AVFormatContext *avfcontext, AVFormatParameters *ap) | |
192 { | |
35 | 193 OggContext *context = avfcontext->priv_data; |
0 | 194 char *buf ; |
195 ogg_page og ; | |
196 AVStream *ast ; | |
404 | 197 |
198 avfcontext->ctx_flags |= AVFMTCTX_NOHEADER; | |
199 | |
0 | 200 ogg_sync_init(&context->oy) ; |
201 buf = ogg_sync_buffer(&context->oy, DECODER_BUFFER_SIZE) ; | |
202 | |
203 if(get_buffer(&avfcontext->pb, buf, DECODER_BUFFER_SIZE) <= 0) | |
204 return -EIO ; | |
205 | |
206 ogg_sync_wrote(&context->oy, DECODER_BUFFER_SIZE) ; | |
207 ogg_sync_pageout(&context->oy, &og) ; | |
208 ogg_stream_init(&context->os, ogg_page_serialno(&og)) ; | |
209 ogg_stream_pagein(&context->os, &og) ; | |
210 | |
211 /* currently only one vorbis stream supported */ | |
212 | |
213 ast = av_new_stream(avfcontext, 0) ; | |
214 if(!ast) | |
215 return AVERROR_NOMEM ; | |
216 | |
217 ast->codec.codec_type = CODEC_TYPE_AUDIO ; | |
218 ast->codec.codec_id = CODEC_ID_VORBIS ; | |
219 | |
220 return 0 ; | |
221 } | |
222 | |
223 | |
224 static int ogg_read_packet(AVFormatContext *avfcontext, AVPacket *pkt) { | |
225 ogg_packet op ; | |
226 | |
227 if(next_packet(avfcontext, &op)) | |
228 return -EIO ; | |
229 if(av_new_packet(pkt, sizeof(ogg_packet) + op.bytes) < 0) | |
230 return -EIO ; | |
231 pkt->stream_index = 0 ; | |
232 memcpy(pkt->data, &op, sizeof(ogg_packet)) ; | |
233 memcpy(pkt->data + sizeof(ogg_packet), op.packet, op.bytes) ; | |
234 | |
235 return sizeof(ogg_packet) + op.bytes ; | |
236 } | |
237 | |
238 | |
239 static int ogg_read_close(AVFormatContext *avfcontext) { | |
240 OggContext *context = avfcontext->priv_data ; | |
241 | |
242 ogg_stream_clear(&context->os) ; | |
243 ogg_sync_clear(&context->oy) ; | |
244 | |
245 return 0 ; | |
246 } | |
247 | |
248 | |
249 static AVInputFormat ogg_iformat = { | |
250 "ogg", | |
251 "Ogg Vorbis", | |
252 sizeof(OggContext), | |
253 NULL, | |
254 ogg_read_header, | |
255 ogg_read_packet, | |
256 ogg_read_close, | |
257 .extensions = "ogg", | |
258 } ; | |
259 | |
260 | |
261 int ogg_init(void) { | |
277
a313e1080322
disable encoders where appropriate (patch courtesy of BERO
melanson
parents:
68
diff
changeset
|
262 #ifdef CONFIG_ENCODERS |
0 | 263 av_register_output_format(&ogg_oformat) ; |
277
a313e1080322
disable encoders where appropriate (patch courtesy of BERO
melanson
parents:
68
diff
changeset
|
264 #endif |
0 | 265 av_register_input_format(&ogg_iformat); |
266 return 0 ; | |
267 } |