Mercurial > libavformat.hg
annotate ogg.c @ 1206:e60bf67d9bf8 libavformat
The reader ignores the size of the ASF data object and keeps on
reading even beyond it.
Therefore if the ASF file includes an index object at its end, the
reader will treat the index like data, but of course will fail since
it thinks that the data is corrupted.
When reading an asf file with an index object, ffmpeg will
complain at the end of the file that it read an invalid header.
Patch by Kohn Emil Dan, < emild A cs P technion P ac P il >
Original thead:
Date: Apr 18, 2006 4:11 PM
Subject: [Ffmpeg-devel] Two ASF related bugs and fixes
author | gpoirier |
---|---|
date | Sat, 29 Jul 2006 16:07:19 +0000 |
parents | d18cc9a1fd02 |
children | 8bf9be9bb107 |
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 | |
13 #include "avformat.h" | |
14 | |
406
ea22a438ca79
fix obnoxious ogg_packet passing from encoder to muxer
michael
parents:
405
diff
changeset
|
15 #undef NDEBUG |
ea22a438ca79
fix obnoxious ogg_packet passing from encoder to muxer
michael
parents:
405
diff
changeset
|
16 #include <assert.h> |
ea22a438ca79
fix obnoxious ogg_packet passing from encoder to muxer
michael
parents:
405
diff
changeset
|
17 |
0 | 18 #define DECODER_BUFFER_SIZE 4096 |
19 | |
20 | |
21 typedef struct OggContext { | |
22 /* output */ | |
23 ogg_stream_state os ; | |
24 int header_handled ; | |
406
ea22a438ca79
fix obnoxious ogg_packet passing from encoder to muxer
michael
parents:
405
diff
changeset
|
25 ogg_packet op; |
0 | 26 |
27 /* input */ | |
28 ogg_sync_state oy ; | |
29 } OggContext ; | |
30 | |
31 | |
858
66cc656ea404
Replace CONFIG_ENCODERS/CONFIG_DECODERS with CONFIG_MUXERS/CONFIG_DEMUXERS
diego
parents:
857
diff
changeset
|
32 #ifdef CONFIG_MUXERS |
885 | 33 static int ogg_write_header(AVFormatContext *avfcontext) |
35 | 34 { |
35 OggContext *context = avfcontext->priv_data; | |
885 | 36 ogg_packet *op= &context->op; |
857 | 37 int n; |
406
ea22a438ca79
fix obnoxious ogg_packet passing from encoder to muxer
michael
parents:
405
diff
changeset
|
38 |
404 | 39 ogg_stream_init(&context->os, 31415); |
885 | 40 |
0 | 41 for(n = 0 ; n < avfcontext->nb_streams ; n++) { |
820
feca73904e67
changing AVCodecContext codec -> *codec in AVStream so additions to AVCodecContext dont randomize AVStream and break binary compatibility
michael
parents:
726
diff
changeset
|
42 AVCodecContext *codec = avfcontext->streams[n]->codec; |
843 | 43 uint8_t *headers = codec->extradata; |
44 int headers_len = codec->extradata_size; | |
45 uint8_t *header_start[3]; | |
46 int header_len[3]; | |
857 | 47 int i, j; |
885 | 48 |
462
b69898ffc92a
move time_base (pts_num/pts_den) from AVFormatContext -> AVStream
michael
parents:
454
diff
changeset
|
49 av_set_pts_info(avfcontext->streams[n], 60, 1, AV_TIME_BASE); |
b69898ffc92a
move time_base (pts_num/pts_den) from AVFormatContext -> AVStream
michael
parents:
454
diff
changeset
|
50 |
843 | 51 for(j=1,i=0;i<2;++i, ++j) { |
52 header_len[i]=0; | |
53 while(j<headers_len && headers[j]==0xff) { | |
54 header_len[i]+=0xff; | |
55 ++j; | |
56 } | |
57 header_len[i]+=headers[j]; | |
58 } | |
59 header_len[2]=headers_len-header_len[0]-header_len[1]-j; | |
60 headers+=j; | |
61 header_start[0] = headers; | |
62 header_start[1] = header_start[0] + header_len[0]; | |
63 header_start[2] = header_start[1] + header_len[1]; | |
0 | 64 |
843 | 65 for(i=0; i < 3; ++i){ |
66 op->bytes = header_len[i]; | |
67 | |
68 op->packet= header_start[i]; | |
407
b9d16c18ee18
remove function call from muxer->encoder and cleanly pass global headers
michael
parents:
406
diff
changeset
|
69 op->b_o_s= op->packetno==0; |
0 | 70 |
407
b9d16c18ee18
remove function call from muxer->encoder and cleanly pass global headers
michael
parents:
406
diff
changeset
|
71 ogg_stream_packetin(&context->os, op); |
b9d16c18ee18
remove function call from muxer->encoder and cleanly pass global headers
michael
parents:
406
diff
changeset
|
72 |
b9d16c18ee18
remove function call from muxer->encoder and cleanly pass global headers
michael
parents:
406
diff
changeset
|
73 op->packetno++; //FIXME multiple streams |
b9d16c18ee18
remove function call from muxer->encoder and cleanly pass global headers
michael
parents:
406
diff
changeset
|
74 } |
0 | 75 |
887 | 76 context->header_handled = 0 ; |
0 | 77 } |
885 | 78 |
0 | 79 return 0 ; |
80 } | |
81 | |
468 | 82 static int ogg_write_packet(AVFormatContext *avfcontext, AVPacket *pkt) |
0 | 83 { |
84 OggContext *context = avfcontext->priv_data ; | |
820
feca73904e67
changing AVCodecContext codec -> *codec in AVStream so additions to AVCodecContext dont randomize AVStream and break binary compatibility
michael
parents:
726
diff
changeset
|
85 AVCodecContext *avctx= avfcontext->streams[pkt->stream_index]->codec; |
406
ea22a438ca79
fix obnoxious ogg_packet passing from encoder to muxer
michael
parents:
405
diff
changeset
|
86 ogg_packet *op= &context->op; |
0 | 87 ogg_page og ; |
468 | 88 int64_t pts; |
406
ea22a438ca79
fix obnoxious ogg_packet passing from encoder to muxer
michael
parents:
405
diff
changeset
|
89 |
468 | 90 pts= av_rescale(pkt->pts, avctx->sample_rate, AV_TIME_BASE); |
406
ea22a438ca79
fix obnoxious ogg_packet passing from encoder to muxer
michael
parents:
405
diff
changeset
|
91 |
ea22a438ca79
fix obnoxious ogg_packet passing from encoder to muxer
michael
parents:
405
diff
changeset
|
92 // av_log(avfcontext, AV_LOG_DEBUG, "M%d\n", size); |
ea22a438ca79
fix obnoxious ogg_packet passing from encoder to muxer
michael
parents:
405
diff
changeset
|
93 |
0 | 94 /* flush header packets so audio starts on a new page */ |
95 | |
96 if(!context->header_handled) { | |
887 | 97 while(ogg_stream_flush(&context->os, &og)) { |
98 put_buffer(&avfcontext->pb, og.header, og.header_len) ; | |
99 put_buffer(&avfcontext->pb, og.body, og.body_len) ; | |
100 put_flush_packet(&avfcontext->pb); | |
101 } | |
102 context->header_handled = 1 ; | |
0 | 103 } |
104 | |
468 | 105 op->packet = (uint8_t*) pkt->data; |
106 op->bytes = pkt->size; | |
406
ea22a438ca79
fix obnoxious ogg_packet passing from encoder to muxer
michael
parents:
405
diff
changeset
|
107 op->b_o_s = op->packetno == 0; |
ea22a438ca79
fix obnoxious ogg_packet passing from encoder to muxer
michael
parents:
405
diff
changeset
|
108 op->granulepos= pts; |
0 | 109 |
406
ea22a438ca79
fix obnoxious ogg_packet passing from encoder to muxer
michael
parents:
405
diff
changeset
|
110 /* correct the fields in the packet -- essential for streaming */ |
885 | 111 |
112 ogg_stream_packetin(&context->os, op); | |
113 | |
406
ea22a438ca79
fix obnoxious ogg_packet passing from encoder to muxer
michael
parents:
405
diff
changeset
|
114 while(ogg_stream_pageout(&context->os, &og)) { |
ea22a438ca79
fix obnoxious ogg_packet passing from encoder to muxer
michael
parents:
405
diff
changeset
|
115 put_buffer(&avfcontext->pb, og.header, og.header_len); |
887 | 116 put_buffer(&avfcontext->pb, og.body, og.body_len); |
117 put_flush_packet(&avfcontext->pb); | |
885 | 118 } |
406
ea22a438ca79
fix obnoxious ogg_packet passing from encoder to muxer
michael
parents:
405
diff
changeset
|
119 op->packetno++; |
0 | 120 |
121 return 0; | |
122 } | |
123 | |
124 | |
125 static int ogg_write_trailer(AVFormatContext *avfcontext) { | |
126 OggContext *context = avfcontext->priv_data ; | |
127 ogg_page og ; | |
128 | |
129 while(ogg_stream_flush(&context->os, &og)) { | |
887 | 130 put_buffer(&avfcontext->pb, og.header, og.header_len) ; |
131 put_buffer(&avfcontext->pb, og.body, og.body_len) ; | |
132 put_flush_packet(&avfcontext->pb); | |
0 | 133 } |
134 | |
135 ogg_stream_clear(&context->os) ; | |
136 return 0 ; | |
137 } | |
138 | |
139 | |
1169 | 140 AVOutputFormat ogg_muxer = { |
0 | 141 "ogg", |
142 "Ogg Vorbis", | |
143 "audio/x-vorbis", | |
144 "ogg", | |
145 sizeof(OggContext), | |
146 CODEC_ID_VORBIS, | |
147 0, | |
148 ogg_write_header, | |
149 ogg_write_packet, | |
150 ogg_write_trailer, | |
151 } ; | |
858
66cc656ea404
Replace CONFIG_ENCODERS/CONFIG_DECODERS with CONFIG_MUXERS/CONFIG_DEMUXERS
diego
parents:
857
diff
changeset
|
152 #endif //CONFIG_MUXERS |
0 | 153 |
726
17178af951b4
Ogg demuxer ported from tcvp by Luca Barbato <lu_zero at gentoo dot org>,
mru
parents:
639
diff
changeset
|
154 #if 0 |
0 | 155 static int next_packet(AVFormatContext *avfcontext, ogg_packet *op) { |
156 OggContext *context = avfcontext->priv_data ; | |
157 ogg_page og ; | |
158 char *buf ; | |
159 | |
160 while(ogg_stream_packetout(&context->os, op) != 1) { | |
161 | |
887 | 162 /* while no pages are available, read in more data to the sync */ |
163 while(ogg_sync_pageout(&context->oy, &og) != 1) { | |
164 buf = ogg_sync_buffer(&context->oy, DECODER_BUFFER_SIZE) ; | |
165 if(get_buffer(&avfcontext->pb, buf, DECODER_BUFFER_SIZE) <= 0) | |
166 return 1 ; | |
167 ogg_sync_wrote(&context->oy, DECODER_BUFFER_SIZE) ; | |
168 } | |
885 | 169 |
887 | 170 /* got a page. Feed it into the stream and get the packet */ |
171 if(ogg_stream_pagein(&context->os, &og) != 0) | |
172 return 1 ; | |
0 | 173 } |
174 | |
175 return 0 ; | |
176 } | |
177 | |
178 | |
179 static int ogg_read_header(AVFormatContext *avfcontext, AVFormatParameters *ap) | |
180 { | |
35 | 181 OggContext *context = avfcontext->priv_data; |
885 | 182 ogg_packet op ; |
0 | 183 char *buf ; |
184 ogg_page og ; | |
185 AVStream *ast ; | |
408 | 186 AVCodecContext *codec; |
187 uint8_t *p; | |
188 int i; | |
885 | 189 |
0 | 190 ogg_sync_init(&context->oy) ; |
191 buf = ogg_sync_buffer(&context->oy, DECODER_BUFFER_SIZE) ; | |
192 | |
193 if(get_buffer(&avfcontext->pb, buf, DECODER_BUFFER_SIZE) <= 0) | |
887 | 194 return AVERROR_IO ; |
885 | 195 |
196 ogg_sync_wrote(&context->oy, DECODER_BUFFER_SIZE) ; | |
0 | 197 ogg_sync_pageout(&context->oy, &og) ; |
198 ogg_stream_init(&context->os, ogg_page_serialno(&og)) ; | |
199 ogg_stream_pagein(&context->os, &og) ; | |
885 | 200 |
0 | 201 /* currently only one vorbis stream supported */ |
202 | |
203 ast = av_new_stream(avfcontext, 0) ; | |
204 if(!ast) | |
887 | 205 return AVERROR_NOMEM ; |
462
b69898ffc92a
move time_base (pts_num/pts_den) from AVFormatContext -> AVStream
michael
parents:
454
diff
changeset
|
206 av_set_pts_info(ast, 60, 1, AV_TIME_BASE); |
0 | 207 |
408 | 208 codec= &ast->codec; |
209 codec->codec_type = CODEC_TYPE_AUDIO; | |
210 codec->codec_id = CODEC_ID_VORBIS; | |
211 for(i=0; i<3; i++){ | |
212 if(next_packet(avfcontext, &op)){ | |
213 return -1; | |
214 } | |
639 | 215 if(op.bytes >= (1<<16) || op.bytes < 0) |
216 return -1; | |
408 | 217 codec->extradata_size+= 2 + op.bytes; |
587
fe24632a577b
allocate a few bytes more for extradata so the bitstream reader if its used by the codec for parsing extardata, doesnt read over the end
michael
parents:
486
diff
changeset
|
218 codec->extradata= av_realloc(codec->extradata, codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE); |
884
2ece9c9dd94c
malloc padding to avoid reading past the malloc()ed area.
henry
parents:
858
diff
changeset
|
219 memset(codec->extradata + codec->extradata_size, 0, FF_INPUT_BUFFER_PADDING_SIZE); |
408 | 220 p= codec->extradata + codec->extradata_size - 2 - op.bytes; |
221 *(p++)= op.bytes>>8; | |
222 *(p++)= op.bytes&0xFF; | |
223 memcpy(p, op.packet, op.bytes); | |
224 } | |
225 | |
0 | 226 return 0 ; |
227 } | |
228 | |
229 | |
230 static int ogg_read_packet(AVFormatContext *avfcontext, AVPacket *pkt) { | |
231 ogg_packet op ; | |
232 | |
885 | 233 if(next_packet(avfcontext, &op)) |
887 | 234 return AVERROR_IO ; |
405
04d7dda7ccd5
kill obnoxious ogg_packet passing from demuxer to decoder
michael
parents:
404
diff
changeset
|
235 if(av_new_packet(pkt, op.bytes) < 0) |
887 | 236 return AVERROR_IO ; |
0 | 237 pkt->stream_index = 0 ; |
405
04d7dda7ccd5
kill obnoxious ogg_packet passing from demuxer to decoder
michael
parents:
404
diff
changeset
|
238 memcpy(pkt->data, op.packet, op.bytes); |
454 | 239 if(avfcontext->streams[0]->codec.sample_rate && op.granulepos!=-1) |
240 pkt->pts= av_rescale(op.granulepos, AV_TIME_BASE, avfcontext->streams[0]->codec.sample_rate); | |
241 // printf("%lld %d %d\n", pkt->pts, (int)op.granulepos, avfcontext->streams[0]->codec.sample_rate); | |
0 | 242 |
405
04d7dda7ccd5
kill obnoxious ogg_packet passing from demuxer to decoder
michael
parents:
404
diff
changeset
|
243 return op.bytes; |
0 | 244 } |
245 | |
246 | |
247 static int ogg_read_close(AVFormatContext *avfcontext) { | |
248 OggContext *context = avfcontext->priv_data ; | |
249 | |
250 ogg_stream_clear(&context->os) ; | |
251 ogg_sync_clear(&context->oy) ; | |
252 | |
253 return 0 ; | |
254 } | |
255 | |
256 | |
1169 | 257 static AVInputFormat ogg_iformat = { |
0 | 258 "ogg", |
259 "Ogg Vorbis", | |
260 sizeof(OggContext), | |
261 NULL, | |
262 ogg_read_header, | |
263 ogg_read_packet, | |
264 ogg_read_close, | |
265 .extensions = "ogg", | |
266 } ; | |
726
17178af951b4
Ogg demuxer ported from tcvp by Luca Barbato <lu_zero at gentoo dot org>,
mru
parents:
639
diff
changeset
|
267 #endif |