00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 #include <stdio.h>
00032 #include "libavutil/avassert.h"
00033 #include "oggdec.h"
00034 #include "avformat.h"
00035 #include "internal.h"
00036 #include "vorbiscomment.h"
00037
00038 #define MAX_PAGE_SIZE 65307
00039 #define DECODER_BUFFER_SIZE MAX_PAGE_SIZE
00040
00041 static const struct ogg_codec * const ogg_codecs[] = {
00042 &ff_skeleton_codec,
00043 &ff_dirac_codec,
00044 &ff_speex_codec,
00045 &ff_vorbis_codec,
00046 &ff_theora_codec,
00047 &ff_flac_codec,
00048 &ff_celt_codec,
00049 &ff_opus_codec,
00050 &ff_old_dirac_codec,
00051 &ff_old_flac_codec,
00052 &ff_ogm_video_codec,
00053 &ff_ogm_audio_codec,
00054 &ff_ogm_text_codec,
00055 &ff_ogm_old_codec,
00056 NULL
00057 };
00058
00059 static int64_t ogg_calc_pts(AVFormatContext *s, int idx, int64_t *dts);
00060 static int ogg_read_close(AVFormatContext *s);
00061
00062
00063 static int ogg_save(AVFormatContext *s)
00064 {
00065 struct ogg *ogg = s->priv_data;
00066 struct ogg_state *ost =
00067 av_malloc(sizeof (*ost) + (ogg->nstreams-1) * sizeof (*ogg->streams));
00068 int i;
00069 ost->pos = avio_tell (s->pb);
00070 ost->curidx = ogg->curidx;
00071 ost->next = ogg->state;
00072 ost->nstreams = ogg->nstreams;
00073 memcpy(ost->streams, ogg->streams, ogg->nstreams * sizeof(*ogg->streams));
00074
00075 for (i = 0; i < ogg->nstreams; i++){
00076 struct ogg_stream *os = ogg->streams + i;
00077 os->buf = av_mallocz (os->bufsize + FF_INPUT_BUFFER_PADDING_SIZE);
00078 memcpy (os->buf, ost->streams[i].buf, os->bufpos);
00079 }
00080
00081 ogg->state = ost;
00082
00083 return 0;
00084 }
00085
00086 static int ogg_restore(AVFormatContext *s, int discard)
00087 {
00088 struct ogg *ogg = s->priv_data;
00089 AVIOContext *bc = s->pb;
00090 struct ogg_state *ost = ogg->state;
00091 int i;
00092
00093 if (!ost)
00094 return 0;
00095
00096 ogg->state = ost->next;
00097
00098 if (!discard){
00099 struct ogg_stream *old_streams = ogg->streams;
00100
00101 for (i = 0; i < ogg->nstreams; i++)
00102 av_free (ogg->streams[i].buf);
00103
00104 avio_seek (bc, ost->pos, SEEK_SET);
00105 ogg->curidx = ost->curidx;
00106 ogg->nstreams = ost->nstreams;
00107 ogg->streams = av_realloc (ogg->streams,
00108 ogg->nstreams * sizeof (*ogg->streams));
00109
00110 if (ogg->streams) {
00111 memcpy(ogg->streams, ost->streams,
00112 ost->nstreams * sizeof(*ogg->streams));
00113 } else {
00114 av_free(old_streams);
00115 ogg->nstreams = 0;
00116 }
00117 }
00118
00119 av_free (ost);
00120
00121 return 0;
00122 }
00123
00124 static int ogg_reset(AVFormatContext *s)
00125 {
00126 struct ogg *ogg = s->priv_data;
00127 int i;
00128 int64_t start_pos = avio_tell(s->pb);
00129
00130 for (i = 0; i < ogg->nstreams; i++){
00131 struct ogg_stream *os = ogg->streams + i;
00132 os->bufpos = 0;
00133 os->pstart = 0;
00134 os->psize = 0;
00135 os->granule = -1;
00136 os->lastpts = AV_NOPTS_VALUE;
00137 os->lastdts = AV_NOPTS_VALUE;
00138 os->sync_pos = -1;
00139 os->page_pos = 0;
00140 os->nsegs = 0;
00141 os->segp = 0;
00142 os->incomplete = 0;
00143 os->got_data = 0;
00144 if (start_pos <= s->data_offset) {
00145 os->lastpts = 0;
00146 }
00147 }
00148
00149 ogg->curidx = -1;
00150
00151 return 0;
00152 }
00153
00154 static const struct ogg_codec *ogg_find_codec(uint8_t *buf, int size)
00155 {
00156 int i;
00157
00158 for (i = 0; ogg_codecs[i]; i++)
00159 if (size >= ogg_codecs[i]->magicsize &&
00160 !memcmp (buf, ogg_codecs[i]->magic, ogg_codecs[i]->magicsize))
00161 return ogg_codecs[i];
00162
00163 return NULL;
00164 }
00165
00171 static int ogg_replace_stream(AVFormatContext *s, uint32_t serial)
00172 {
00173 struct ogg *ogg = s->priv_data;
00174 struct ogg_stream *os;
00175 unsigned bufsize;
00176 uint8_t *buf;
00177 struct ogg_codec *codec;
00178
00179 if (ogg->nstreams != 1) {
00180 av_log_missing_feature(s, "Changing stream parameters in multistream ogg", 0);
00181 return AVERROR_PATCHWELCOME;
00182 }
00183
00184 os = &ogg->streams[0];
00185
00186 buf = os->buf;
00187 bufsize = os->bufsize;
00188 codec = os->codec;
00189
00190 if (!ogg->state || ogg->state->streams[0].private != os->private)
00191 av_freep(&ogg->streams[0].private);
00192
00193
00194
00195 memset(os, 0, sizeof(*os));
00196 os->serial = serial;
00197 os->bufsize = bufsize;
00198 os->buf = buf;
00199 os->header = -1;
00200 os->codec = codec;
00201
00202 return 0;
00203 }
00204
00205 static int ogg_new_stream(AVFormatContext *s, uint32_t serial)
00206 {
00207 struct ogg *ogg = s->priv_data;
00208 int idx = ogg->nstreams;
00209 AVStream *st;
00210 struct ogg_stream *os;
00211 size_t size;
00212
00213 if (ogg->state) {
00214 av_log(s, AV_LOG_ERROR, "New streams are not supposed to be added "
00215 "in between Ogg context save/restore operations.\n");
00216 return AVERROR_BUG;
00217 }
00218
00219
00220 if (av_size_mult(ogg->nstreams + 1, sizeof(*ogg->streams), &size) < 0 ||
00221 !(os = av_realloc(ogg->streams, size)))
00222 return AVERROR(ENOMEM);
00223 ogg->streams = os;
00224 os = ogg->streams + idx;
00225 memset(os, 0, sizeof(*os));
00226 os->serial = serial;
00227 os->bufsize = DECODER_BUFFER_SIZE;
00228 os->buf = av_malloc(os->bufsize + FF_INPUT_BUFFER_PADDING_SIZE);
00229 os->header = -1;
00230 os->start_granule = OGG_NOGRANULE_VALUE;
00231 if (!os->buf)
00232 return AVERROR(ENOMEM);
00233
00234
00235 st = avformat_new_stream(s, NULL);
00236 if (!st) {
00237 av_freep(&os->buf);
00238 return AVERROR(ENOMEM);
00239 }
00240 st->id = idx;
00241 avpriv_set_pts_info(st, 64, 1, 1000000);
00242
00243 ogg->nstreams++;
00244 return idx;
00245 }
00246
00247 static int ogg_new_buf(struct ogg *ogg, int idx)
00248 {
00249 struct ogg_stream *os = ogg->streams + idx;
00250 uint8_t *nb = av_malloc(os->bufsize + FF_INPUT_BUFFER_PADDING_SIZE);
00251 int size = os->bufpos - os->pstart;
00252 if(os->buf){
00253 memcpy(nb, os->buf + os->pstart, size);
00254 av_free(os->buf);
00255 }
00256 os->buf = nb;
00257 os->bufpos = size;
00258 os->pstart = 0;
00259
00260 return 0;
00261 }
00262
00263 static int data_packets_seen(const struct ogg *ogg)
00264 {
00265 int i;
00266
00267 for (i = 0; i < ogg->nstreams; i++)
00268 if (ogg->streams[i].got_data)
00269 return 1;
00270 return 0;
00271 }
00272
00273 static int ogg_read_page(AVFormatContext *s, int *sid)
00274 {
00275 AVIOContext *bc = s->pb;
00276 struct ogg *ogg = s->priv_data;
00277 struct ogg_stream *os;
00278 int ret, i = 0;
00279 int flags, nsegs;
00280 uint64_t gp;
00281 uint32_t serial;
00282 int size, idx;
00283 uint8_t sync[4];
00284 int sp = 0;
00285
00286 ret = avio_read(bc, sync, 4);
00287 if (ret < 4)
00288 return ret < 0 ? ret : AVERROR_EOF;
00289
00290 do{
00291 int c;
00292
00293 if (sync[sp & 3] == 'O' &&
00294 sync[(sp + 1) & 3] == 'g' &&
00295 sync[(sp + 2) & 3] == 'g' && sync[(sp + 3) & 3] == 'S')
00296 break;
00297
00298 c = avio_r8(bc);
00299 if (url_feof(bc))
00300 return AVERROR_EOF;
00301 sync[sp++ & 3] = c;
00302 }while (i++ < MAX_PAGE_SIZE);
00303
00304 if (i >= MAX_PAGE_SIZE){
00305 av_log (s, AV_LOG_INFO, "ogg, can't find sync word\n");
00306 return AVERROR_INVALIDDATA;
00307 }
00308
00309 if (avio_r8(bc) != 0){
00310 av_log (s, AV_LOG_ERROR, "ogg page, unsupported version\n");
00311 return AVERROR_INVALIDDATA;
00312 }
00313
00314 flags = avio_r8(bc);
00315 gp = avio_rl64 (bc);
00316 serial = avio_rl32 (bc);
00317 avio_skip(bc, 8);
00318 nsegs = avio_r8(bc);
00319
00320 idx = ogg_find_stream (ogg, serial);
00321 if (idx < 0){
00322 if (data_packets_seen(ogg))
00323 idx = ogg_replace_stream(s, serial);
00324 else
00325 idx = ogg_new_stream(s, serial);
00326
00327 if (idx < 0) {
00328 av_log(s, AV_LOG_ERROR, "failed to create or replace stream\n");
00329 return idx;
00330 }
00331 }
00332
00333 os = ogg->streams + idx;
00334 os->page_pos = avio_tell(bc) - 27;
00335
00336 if(os->psize > 0)
00337 ogg_new_buf(ogg, idx);
00338
00339 ret = avio_read(bc, os->segments, nsegs);
00340 if (ret < nsegs)
00341 return ret < 0 ? ret : AVERROR_EOF;
00342
00343 os->nsegs = nsegs;
00344 os->segp = 0;
00345
00346 size = 0;
00347 for (i = 0; i < nsegs; i++)
00348 size += os->segments[i];
00349
00350 if (!(flags & OGG_FLAG_BOS))
00351 os->got_data = 1;
00352
00353 if (flags & OGG_FLAG_CONT || os->incomplete){
00354 if (!os->psize){
00355
00356
00357
00358 while (os->segp < os->nsegs){
00359 int seg = os->segments[os->segp++];
00360 os->pstart += seg;
00361 if (seg < 255)
00362 break;
00363 }
00364 os->sync_pos = os->page_pos;
00365 }
00366 }else{
00367 os->psize = 0;
00368 os->sync_pos = os->page_pos;
00369 }
00370
00371 if (os->bufsize - os->bufpos < size){
00372 uint8_t *nb = av_malloc ((os->bufsize *= 2) + FF_INPUT_BUFFER_PADDING_SIZE);
00373 memcpy (nb, os->buf, os->bufpos);
00374 av_free (os->buf);
00375 os->buf = nb;
00376 }
00377
00378 ret = avio_read(bc, os->buf + os->bufpos, size);
00379 if (ret < size)
00380 return ret < 0 ? ret : AVERROR_EOF;
00381
00382 os->bufpos += size;
00383 os->granule = gp;
00384 os->flags = flags;
00385
00386 memset(os->buf + os->bufpos, 0, FF_INPUT_BUFFER_PADDING_SIZE);
00387 if (sid)
00388 *sid = idx;
00389
00390 return 0;
00391 }
00392
00400 static int ogg_packet(AVFormatContext *s, int *sid, int *dstart, int *dsize,
00401 int64_t *fpos)
00402 {
00403 struct ogg *ogg = s->priv_data;
00404 int idx, i, ret;
00405 struct ogg_stream *os;
00406 int complete = 0;
00407 int segp = 0, psize = 0;
00408
00409 av_dlog(s, "ogg_packet: curidx=%i\n", ogg->curidx);
00410 if (sid)
00411 *sid = -1;
00412
00413 do{
00414 idx = ogg->curidx;
00415
00416 while (idx < 0){
00417 ret = ogg_read_page(s, &idx);
00418 if (ret < 0)
00419 return ret;
00420 }
00421
00422 os = ogg->streams + idx;
00423
00424 av_dlog(s, "ogg_packet: idx=%d pstart=%d psize=%d segp=%d nsegs=%d\n",
00425 idx, os->pstart, os->psize, os->segp, os->nsegs);
00426
00427 if (!os->codec){
00428 if (os->header < 0){
00429 os->codec = ogg_find_codec (os->buf, os->bufpos);
00430 if (!os->codec){
00431 av_log(s, AV_LOG_WARNING, "Codec not found\n");
00432 os->header = 0;
00433 return 0;
00434 }
00435 }else{
00436 return 0;
00437 }
00438 }
00439
00440 segp = os->segp;
00441 psize = os->psize;
00442
00443 while (os->segp < os->nsegs){
00444 int ss = os->segments[os->segp++];
00445 os->psize += ss;
00446 if (ss < 255){
00447 complete = 1;
00448 break;
00449 }
00450 }
00451
00452 if (!complete && os->segp == os->nsegs){
00453 ogg->curidx = -1;
00454
00455
00456
00457
00458 os->incomplete = !!os->psize;
00459 }
00460 }while (!complete);
00461
00462
00463 if (os->granule == -1)
00464 av_log(s, AV_LOG_WARNING, "Page at %"PRId64" is missing granule\n", os->page_pos);
00465
00466 ogg->curidx = idx;
00467 os->incomplete = 0;
00468
00469 if (os->header) {
00470 os->header = os->codec->header (s, idx);
00471 if (!os->header){
00472 os->segp = segp;
00473 os->psize = psize;
00474
00475
00476
00477
00478 ogg->headers = 1;
00479
00480
00481
00482 if (!s->data_offset)
00483 s->data_offset = os->sync_pos;
00484 for (i = 0; i < ogg->nstreams; i++) {
00485 struct ogg_stream *cur_os = ogg->streams + i;
00486
00487
00488
00489 if (cur_os->incomplete)
00490 s->data_offset = FFMIN(s->data_offset, cur_os->sync_pos);
00491 }
00492 }else{
00493 os->nb_header++;
00494 os->pstart += os->psize;
00495 os->psize = 0;
00496 }
00497 } else {
00498 os->pflags = 0;
00499 os->pduration = 0;
00500 if (os->codec && os->codec->packet)
00501 os->codec->packet (s, idx);
00502 if (sid)
00503 *sid = idx;
00504 if (dstart)
00505 *dstart = os->pstart;
00506 if (dsize)
00507 *dsize = os->psize;
00508 if (fpos)
00509 *fpos = os->sync_pos;
00510 os->pstart += os->psize;
00511 os->psize = 0;
00512 if(os->pstart == os->bufpos)
00513 os->bufpos = os->pstart = 0;
00514 os->sync_pos = os->page_pos;
00515 }
00516
00517
00518
00519 os->page_end = 1;
00520 for (i = os->segp; i < os->nsegs; i++)
00521 if (os->segments[i] < 255) {
00522 os->page_end = 0;
00523 break;
00524 }
00525
00526 if (os->segp == os->nsegs)
00527 ogg->curidx = -1;
00528
00529 return 0;
00530 }
00531
00532 static int ogg_get_length(AVFormatContext *s)
00533 {
00534 struct ogg *ogg = s->priv_data;
00535 int i;
00536 int64_t size, end;
00537 int streams_left=0;
00538
00539 if(!s->pb->seekable)
00540 return 0;
00541
00542
00543 if (s->duration != AV_NOPTS_VALUE)
00544 return 0;
00545
00546 size = avio_size(s->pb);
00547 if(size < 0)
00548 return 0;
00549 end = size > MAX_PAGE_SIZE? size - MAX_PAGE_SIZE: 0;
00550
00551 ogg_save (s);
00552 avio_seek (s->pb, end, SEEK_SET);
00553
00554 while (!ogg_read_page (s, &i)){
00555 if (ogg->streams[i].granule != -1 && ogg->streams[i].granule != 0 &&
00556 ogg->streams[i].codec) {
00557 s->streams[i]->duration =
00558 ogg_gptopts (s, i, ogg->streams[i].granule, NULL);
00559 if (s->streams[i]->start_time != AV_NOPTS_VALUE){
00560 s->streams[i]->duration -= s->streams[i]->start_time;
00561 streams_left-= (ogg->streams[i].got_start==-1);
00562 ogg->streams[i].got_start= 1;
00563 }else if(!ogg->streams[i].got_start){
00564 ogg->streams[i].got_start= -1;
00565 streams_left++;
00566 }
00567 }
00568 }
00569
00570 ogg_restore (s, 0);
00571
00572 ogg_save (s);
00573 avio_seek (s->pb, s->data_offset, SEEK_SET);
00574 ogg_reset(s);
00575 while (streams_left > 0 && !ogg_packet(s, &i, NULL, NULL, NULL)) {
00576 int64_t pts;
00577 if (i < 0) continue;
00578 pts = ogg_calc_pts(s, i, NULL);
00579 if (pts != AV_NOPTS_VALUE && s->streams[i]->start_time == AV_NOPTS_VALUE && !ogg->streams[i].got_start){
00580 s->streams[i]->duration -= pts;
00581 ogg->streams[i].got_start= 1;
00582 streams_left--;
00583 }else if(s->streams[i]->start_time != AV_NOPTS_VALUE && !ogg->streams[i].got_start){
00584 ogg->streams[i].got_start= 1;
00585 streams_left--;
00586 }
00587 }
00588 ogg_restore (s, 0);
00589
00590 return 0;
00591 }
00592
00593 static int ogg_read_header(AVFormatContext *s)
00594 {
00595 struct ogg *ogg = s->priv_data;
00596 int ret, i;
00597
00598 ogg->curidx = -1;
00599
00600
00601 do {
00602 ret = ogg_packet(s, NULL, NULL, NULL, NULL);
00603 if (ret < 0) {
00604 ogg_read_close(s);
00605 return ret;
00606 }
00607 } while (!ogg->headers);
00608 av_dlog(s, "found headers\n");
00609
00610 for (i = 0; i < ogg->nstreams; i++) {
00611 struct ogg_stream *os = ogg->streams + i;
00612
00613 if (ogg->streams[i].header < 0) {
00614 av_log(s, AV_LOG_ERROR, "Header parsing failed for stream %d\n", i);
00615 ogg->streams[i].codec = NULL;
00616 } else if (os->codec && os->nb_header < os->codec->nb_header) {
00617 av_log(s, AV_LOG_WARNING, "Number of headers (%d) mismatch for stream %d\n", os->nb_header, i);
00618 }
00619 if (os->start_granule != OGG_NOGRANULE_VALUE)
00620 os->lastpts = s->streams[i]->start_time =
00621 ogg_gptopts(s, i, os->start_granule, NULL);
00622 }
00623
00624
00625 ogg_get_length (s);
00626
00627 return 0;
00628 }
00629
00630 static int64_t ogg_calc_pts(AVFormatContext *s, int idx, int64_t *dts)
00631 {
00632 struct ogg *ogg = s->priv_data;
00633 struct ogg_stream *os = ogg->streams + idx;
00634 int64_t pts = AV_NOPTS_VALUE;
00635
00636 if (dts)
00637 *dts = AV_NOPTS_VALUE;
00638
00639 if (os->lastpts != AV_NOPTS_VALUE) {
00640 pts = os->lastpts;
00641 os->lastpts = AV_NOPTS_VALUE;
00642 }
00643 if (os->lastdts != AV_NOPTS_VALUE) {
00644 if (dts)
00645 *dts = os->lastdts;
00646 os->lastdts = AV_NOPTS_VALUE;
00647 }
00648 if (os->page_end) {
00649 if (os->granule != -1LL) {
00650 if (os->codec && os->codec->granule_is_start)
00651 pts = ogg_gptopts(s, idx, os->granule, dts);
00652 else
00653 os->lastpts = ogg_gptopts(s, idx, os->granule, &os->lastdts);
00654 os->granule = -1LL;
00655 }
00656 }
00657 return pts;
00658 }
00659
00660 static void ogg_validate_keyframe(AVFormatContext *s, int idx, int pstart, int psize)
00661 {
00662 struct ogg *ogg = s->priv_data;
00663 struct ogg_stream *os = ogg->streams + idx;
00664 if (psize && s->streams[idx]->codec->codec_id == AV_CODEC_ID_THEORA) {
00665 if (!!(os->pflags & AV_PKT_FLAG_KEY) != !(os->buf[pstart] & 0x40)) {
00666 os->pflags ^= AV_PKT_FLAG_KEY;
00667 av_log(s, AV_LOG_WARNING, "Broken file, %skeyframe not correctly marked.\n",
00668 (os->pflags & AV_PKT_FLAG_KEY) ? "" : "non-");
00669 }
00670 }
00671 }
00672
00673 static int ogg_read_packet(AVFormatContext *s, AVPacket *pkt)
00674 {
00675 struct ogg *ogg;
00676 struct ogg_stream *os;
00677 int idx, ret;
00678 int pstart, psize;
00679 int64_t fpos, pts, dts;
00680
00681
00682 retry:
00683 do{
00684 ret = ogg_packet(s, &idx, &pstart, &psize, &fpos);
00685 if (ret < 0)
00686 return ret;
00687 }while (idx < 0 || !s->streams[idx]);
00688
00689 ogg = s->priv_data;
00690 os = ogg->streams + idx;
00691
00692
00693 pts = ogg_calc_pts(s, idx, &dts);
00694 ogg_validate_keyframe(s, idx, pstart, psize);
00695
00696 if (os->keyframe_seek && !(os->pflags & AV_PKT_FLAG_KEY))
00697 goto retry;
00698 os->keyframe_seek = 0;
00699
00700
00701 ret = av_new_packet(pkt, psize);
00702 if (ret < 0)
00703 return ret;
00704 pkt->stream_index = idx;
00705 memcpy (pkt->data, os->buf + pstart, psize);
00706
00707 pkt->pts = pts;
00708 pkt->dts = dts;
00709 pkt->flags = os->pflags;
00710 pkt->duration = os->pduration;
00711 pkt->pos = fpos;
00712
00713 return psize;
00714 }
00715
00716 static int ogg_read_close(AVFormatContext *s)
00717 {
00718 struct ogg *ogg = s->priv_data;
00719 int i;
00720
00721 for (i = 0; i < ogg->nstreams; i++){
00722 av_free (ogg->streams[i].buf);
00723 av_free (ogg->streams[i].private);
00724 }
00725 av_free (ogg->streams);
00726 return 0;
00727 }
00728
00729 static int64_t ogg_read_timestamp(AVFormatContext *s, int stream_index,
00730 int64_t *pos_arg, int64_t pos_limit)
00731 {
00732 struct ogg *ogg = s->priv_data;
00733 AVIOContext *bc = s->pb;
00734 int64_t pts = AV_NOPTS_VALUE;
00735 int64_t keypos = -1;
00736 int i;
00737 int pstart, psize;
00738 avio_seek(bc, *pos_arg, SEEK_SET);
00739 ogg_reset(s);
00740
00741 while (avio_tell(bc) <= pos_limit && !ogg_packet(s, &i, &pstart, &psize, pos_arg)) {
00742 if (i == stream_index) {
00743 struct ogg_stream *os = ogg->streams + stream_index;
00744 pts = ogg_calc_pts(s, i, NULL);
00745 ogg_validate_keyframe(s, i, pstart, psize);
00746 if (os->pflags & AV_PKT_FLAG_KEY) {
00747 keypos = *pos_arg;
00748 } else if (os->keyframe_seek) {
00749
00750
00751 if (keypos >= 0)
00752 *pos_arg = keypos;
00753 else
00754 pts = AV_NOPTS_VALUE;
00755 }
00756 }
00757 if (pts != AV_NOPTS_VALUE)
00758 break;
00759 }
00760 ogg_reset(s);
00761 return pts;
00762 }
00763
00764 static int ogg_read_seek(AVFormatContext *s, int stream_index,
00765 int64_t timestamp, int flags)
00766 {
00767 struct ogg *ogg = s->priv_data;
00768 struct ogg_stream *os = ogg->streams + stream_index;
00769 int ret;
00770
00771 av_assert0(stream_index < ogg->nstreams);
00772
00773
00774 ogg_reset(s);
00775
00776
00777
00778 if (s->streams[stream_index]->codec->codec_type == AVMEDIA_TYPE_VIDEO
00779 && !(flags & AVSEEK_FLAG_ANY))
00780 os->keyframe_seek = 1;
00781
00782 ret = ff_seek_frame_binary(s, stream_index, timestamp, flags);
00783 os = ogg->streams + stream_index;
00784 if (ret < 0)
00785 os->keyframe_seek = 0;
00786 return ret;
00787 }
00788
00789 static int ogg_probe(AVProbeData *p)
00790 {
00791 if (!memcmp("OggS", p->buf, 5) && p->buf[5] <= 0x7)
00792 return AVPROBE_SCORE_MAX;
00793 return 0;
00794 }
00795
00796 AVInputFormat ff_ogg_demuxer = {
00797 .name = "ogg",
00798 .long_name = NULL_IF_CONFIG_SMALL("Ogg"),
00799 .priv_data_size = sizeof(struct ogg),
00800 .read_probe = ogg_probe,
00801 .read_header = ogg_read_header,
00802 .read_packet = ogg_read_packet,
00803 .read_close = ogg_read_close,
00804 .read_seek = ogg_read_seek,
00805 .read_timestamp = ogg_read_timestamp,
00806 .extensions = "ogg",
00807 .flags = AVFMT_GENERIC_INDEX,
00808 };