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