Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
Conflicts:
Changelog
... | ... |
@@ -57,6 +57,7 @@ static const struct ogg_codec * const ogg_codecs[] = { |
57 | 57 |
}; |
58 | 58 |
|
59 | 59 |
static int64_t ogg_calc_pts(AVFormatContext *s, int idx, int64_t *dts); |
60 |
+static int ogg_new_stream(AVFormatContext *s, uint32_t serial); |
|
60 | 61 |
|
61 | 62 |
//FIXME We could avoid some structure duplication |
62 | 63 |
static int ogg_save(AVFormatContext *s) |
... | ... |
@@ -169,30 +170,48 @@ static const struct ogg_codec *ogg_find_codec(uint8_t *buf, int size) |
169 | 169 |
* situation where a new audio stream spawn (identified with a new serial) and |
170 | 170 |
* must replace the previous one (track switch). |
171 | 171 |
*/ |
172 |
-static int ogg_replace_stream(AVFormatContext *s, uint32_t serial) |
|
172 |
+static int ogg_replace_stream(AVFormatContext *s, uint32_t serial, int nsegs) |
|
173 | 173 |
{ |
174 | 174 |
struct ogg *ogg = s->priv_data; |
175 | 175 |
struct ogg_stream *os; |
176 | 176 |
unsigned bufsize; |
177 | 177 |
uint8_t *buf; |
178 | 178 |
const struct ogg_codec *codec; |
179 |
- |
|
180 |
- if (ogg->nstreams != 1) { |
|
179 |
+ int i = 0; |
|
180 |
+ |
|
181 |
+ if (s->pb->seekable) { |
|
182 |
+ uint8_t magic[8]; |
|
183 |
+ int64_t pos = avio_tell(s->pb); |
|
184 |
+ avio_skip(s->pb, nsegs); |
|
185 |
+ avio_read(s->pb, magic, sizeof(magic)); |
|
186 |
+ avio_seek(s->pb, pos, SEEK_SET); |
|
187 |
+ codec = ogg_find_codec(magic, sizeof(magic)); |
|
188 |
+ if (!codec) { |
|
189 |
+ av_log(s, AV_LOG_ERROR, "Cannot identify new stream\n"); |
|
190 |
+ return AVERROR_INVALIDDATA; |
|
191 |
+ } |
|
192 |
+ for (i = 0; i < ogg->nstreams; i++) { |
|
193 |
+ if (ogg->streams[i].codec == codec) |
|
194 |
+ break; |
|
195 |
+ } |
|
196 |
+ if (i >= ogg->nstreams) |
|
197 |
+ return ogg_new_stream(s, serial); |
|
198 |
+ } else if (ogg->nstreams != 1) { |
|
181 | 199 |
av_log_missing_feature(s, "Changing stream parameters in multistream ogg", 0); |
182 | 200 |
return AVERROR_PATCHWELCOME; |
183 | 201 |
} |
184 | 202 |
|
185 |
- os = &ogg->streams[0]; |
|
203 |
+ os = &ogg->streams[i]; |
|
186 | 204 |
|
187 | 205 |
os->serial = serial; |
188 |
- return 0; |
|
206 |
+ return i; |
|
189 | 207 |
|
190 | 208 |
buf = os->buf; |
191 | 209 |
bufsize = os->bufsize; |
192 | 210 |
codec = os->codec; |
193 | 211 |
|
194 |
- if (!ogg->state || ogg->state->streams[0].private != os->private) |
|
195 |
- av_freep(&ogg->streams[0].private); |
|
212 |
+ if (!ogg->state || ogg->state->streams[i].private != os->private) |
|
213 |
+ av_freep(&ogg->streams[i].private); |
|
196 | 214 |
|
197 | 215 |
/* Set Ogg stream settings similar to what is done in ogg_new_stream(). We |
198 | 216 |
* also re-use the ogg_stream allocated buffer */ |
... | ... |
@@ -203,7 +222,7 @@ static int ogg_replace_stream(AVFormatContext *s, uint32_t serial) |
203 | 203 |
os->header = -1; |
204 | 204 |
os->codec = codec; |
205 | 205 |
|
206 |
- return 0; |
|
206 |
+ return i; |
|
207 | 207 |
} |
208 | 208 |
|
209 | 209 |
static int ogg_new_stream(AVFormatContext *s, uint32_t serial) |
... | ... |
@@ -334,7 +353,7 @@ static int ogg_read_page(AVFormatContext *s, int *sid) |
334 | 334 |
idx = ogg_find_stream(ogg, serial); |
335 | 335 |
if (idx < 0) { |
336 | 336 |
if (data_packets_seen(ogg)) |
337 |
- idx = ogg_replace_stream(s, serial); |
|
337 |
+ idx = ogg_replace_stream(s, serial, nsegs); |
|
338 | 338 |
else |
339 | 339 |
idx = ogg_new_stream(s, serial); |
340 | 340 |
|