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
00032 #include <stdio.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_old_dirac_codec,
00050 &ff_old_flac_codec,
00051 &ff_ogm_video_codec,
00052 &ff_ogm_audio_codec,
00053 &ff_ogm_text_codec,
00054 &ff_ogm_old_codec,
00055 NULL
00056 };
00057
00058
00059 static int ogg_save(AVFormatContext *s)
00060 {
00061 struct ogg *ogg = s->priv_data;
00062 struct ogg_state *ost =
00063 av_malloc(sizeof (*ost) + (ogg->nstreams-1) * sizeof (*ogg->streams));
00064 int i;
00065 ost->pos = avio_tell (s->pb);
00066 ost->curidx = ogg->curidx;
00067 ost->next = ogg->state;
00068 ost->nstreams = ogg->nstreams;
00069 memcpy(ost->streams, ogg->streams, ogg->nstreams * sizeof(*ogg->streams));
00070
00071 for (i = 0; i < ogg->nstreams; i++){
00072 struct ogg_stream *os = ogg->streams + i;
00073 os->buf = av_malloc (os->bufsize);
00074 memset (os->buf, 0, os->bufsize);
00075 memcpy (os->buf, ost->streams[i].buf, os->bufpos);
00076 }
00077
00078 ogg->state = ost;
00079
00080 return 0;
00081 }
00082
00083 static int ogg_restore(AVFormatContext *s, int discard)
00084 {
00085 struct ogg *ogg = s->priv_data;
00086 AVIOContext *bc = s->pb;
00087 struct ogg_state *ost = ogg->state;
00088 int i;
00089
00090 if (!ost)
00091 return 0;
00092
00093 ogg->state = ost->next;
00094
00095 if (!discard){
00096 struct ogg_stream *old_streams = ogg->streams;
00097
00098 for (i = 0; i < ogg->nstreams; i++)
00099 av_free (ogg->streams[i].buf);
00100
00101 avio_seek (bc, ost->pos, SEEK_SET);
00102 ogg->curidx = ost->curidx;
00103 ogg->nstreams = ost->nstreams;
00104 ogg->streams = av_realloc (ogg->streams,
00105 ogg->nstreams * sizeof (*ogg->streams));
00106
00107 if (ogg->streams) {
00108 memcpy(ogg->streams, ost->streams,
00109 ost->nstreams * sizeof(*ogg->streams));
00110 } else {
00111 av_free(old_streams);
00112 ogg->nstreams = 0;
00113 }
00114 }
00115
00116 av_free (ost);
00117
00118 return 0;
00119 }
00120
00121 static int ogg_reset(struct ogg *ogg)
00122 {
00123 int i;
00124
00125 for (i = 0; i < ogg->nstreams; i++){
00126 struct ogg_stream *os = ogg->streams + i;
00127 os->bufpos = 0;
00128 os->pstart = 0;
00129 os->psize = 0;
00130 os->granule = -1;
00131 os->lastpts = AV_NOPTS_VALUE;
00132 os->lastdts = AV_NOPTS_VALUE;
00133 os->sync_pos = -1;
00134 os->page_pos = 0;
00135 os->nsegs = 0;
00136 os->segp = 0;
00137 os->incomplete = 0;
00138 }
00139
00140 ogg->curidx = -1;
00141
00142 return 0;
00143 }
00144
00145 static const struct ogg_codec *ogg_find_codec(uint8_t *buf, int size)
00146 {
00147 int i;
00148
00149 for (i = 0; ogg_codecs[i]; i++)
00150 if (size >= ogg_codecs[i]->magicsize &&
00151 !memcmp (buf, ogg_codecs[i]->magic, ogg_codecs[i]->magicsize))
00152 return ogg_codecs[i];
00153
00154 return NULL;
00155 }
00156
00157 static int ogg_new_stream(AVFormatContext *s, uint32_t serial, int new_avstream)
00158 {
00159
00160 struct ogg *ogg = s->priv_data;
00161 int idx = ogg->nstreams++;
00162 AVStream *st;
00163 struct ogg_stream *os;
00164
00165 ogg->streams = av_realloc (ogg->streams,
00166 ogg->nstreams * sizeof (*ogg->streams));
00167 memset (ogg->streams + idx, 0, sizeof (*ogg->streams));
00168 os = ogg->streams + idx;
00169 os->serial = serial;
00170 os->bufsize = DECODER_BUFFER_SIZE;
00171 os->buf = av_malloc(os->bufsize);
00172 os->header = -1;
00173
00174 if (new_avstream) {
00175 st = avformat_new_stream(s, NULL);
00176 if (!st)
00177 return AVERROR(ENOMEM);
00178
00179 st->id = idx;
00180 avpriv_set_pts_info(st, 64, 1, 1000000);
00181 }
00182
00183 return idx;
00184 }
00185
00186 static int ogg_new_buf(struct ogg *ogg, int idx)
00187 {
00188 struct ogg_stream *os = ogg->streams + idx;
00189 uint8_t *nb = av_malloc(os->bufsize);
00190 int size = os->bufpos - os->pstart;
00191 if(os->buf){
00192 memcpy(nb, os->buf + os->pstart, size);
00193 av_free(os->buf);
00194 }
00195 os->buf = nb;
00196 os->bufpos = size;
00197 os->pstart = 0;
00198
00199 return 0;
00200 }
00201
00202 static int ogg_read_page(AVFormatContext *s, int *str)
00203 {
00204 AVIOContext *bc = s->pb;
00205 struct ogg *ogg = s->priv_data;
00206 struct ogg_stream *os;
00207 int ret, i = 0;
00208 int flags, nsegs;
00209 uint64_t gp;
00210 uint32_t serial;
00211 int size, idx;
00212 uint8_t sync[4];
00213 int sp = 0;
00214
00215 ret = avio_read(bc, sync, 4);
00216 if (ret < 4)
00217 return ret < 0 ? ret : AVERROR_EOF;
00218
00219 do{
00220 int c;
00221
00222 if (sync[sp & 3] == 'O' &&
00223 sync[(sp + 1) & 3] == 'g' &&
00224 sync[(sp + 2) & 3] == 'g' && sync[(sp + 3) & 3] == 'S')
00225 break;
00226
00227 c = avio_r8(bc);
00228 if (bc->eof_reached)
00229 return AVERROR_EOF;
00230 sync[sp++ & 3] = c;
00231 }while (i++ < MAX_PAGE_SIZE);
00232
00233 if (i >= MAX_PAGE_SIZE){
00234 av_log (s, AV_LOG_INFO, "ogg, can't find sync word\n");
00235 return AVERROR_INVALIDDATA;
00236 }
00237
00238 if (avio_r8(bc) != 0)
00239 return AVERROR_INVALIDDATA;
00240
00241 flags = avio_r8(bc);
00242 gp = avio_rl64 (bc);
00243 serial = avio_rl32 (bc);
00244 avio_skip(bc, 8);
00245 nsegs = avio_r8(bc);
00246
00247 idx = ogg_find_stream (ogg, serial);
00248 if (idx < 0){
00249 if (ogg->headers) {
00250 int n;
00251
00252 for (n = 0; n < ogg->nstreams; n++) {
00253 av_freep(&ogg->streams[n].buf);
00254 if (!ogg->state || ogg->state->streams[n].private != ogg->streams[n].private)
00255 av_freep(&ogg->streams[n].private);
00256 }
00257 ogg->curidx = -1;
00258 ogg->nstreams = 0;
00259 idx = ogg_new_stream(s, serial, 0);
00260 } else {
00261 idx = ogg_new_stream(s, serial, 1);
00262 }
00263 if (idx < 0)
00264 return idx;
00265 }
00266
00267 os = ogg->streams + idx;
00268 os->page_pos = avio_tell(bc) - 27;
00269
00270 if(os->psize > 0)
00271 ogg_new_buf(ogg, idx);
00272
00273 ret = avio_read(bc, os->segments, nsegs);
00274 if (ret < nsegs)
00275 return ret < 0 ? ret : AVERROR_EOF;
00276
00277 os->nsegs = nsegs;
00278 os->segp = 0;
00279
00280 size = 0;
00281 for (i = 0; i < nsegs; i++)
00282 size += os->segments[i];
00283
00284 if (flags & OGG_FLAG_CONT || os->incomplete){
00285 if (!os->psize){
00286 while (os->segp < os->nsegs){
00287 int seg = os->segments[os->segp++];
00288 os->pstart += seg;
00289 if (seg < 255)
00290 break;
00291 }
00292 os->sync_pos = os->page_pos;
00293 }
00294 }else{
00295 os->psize = 0;
00296 os->sync_pos = os->page_pos;
00297 }
00298
00299 if (os->bufsize - os->bufpos < size){
00300 uint8_t *nb = av_malloc (os->bufsize *= 2);
00301 memcpy (nb, os->buf, os->bufpos);
00302 av_free (os->buf);
00303 os->buf = nb;
00304 }
00305
00306 ret = avio_read(bc, os->buf + os->bufpos, size);
00307 if (ret < size)
00308 return ret < 0 ? ret : AVERROR_EOF;
00309
00310 os->bufpos += size;
00311 os->granule = gp;
00312 os->flags = flags;
00313
00314 if (str)
00315 *str = idx;
00316
00317 return 0;
00318 }
00319
00320 static int ogg_packet(AVFormatContext *s, int *str, int *dstart, int *dsize,
00321 int64_t *fpos)
00322 {
00323 struct ogg *ogg = s->priv_data;
00324 int idx, i, ret;
00325 struct ogg_stream *os;
00326 int complete = 0;
00327 int segp = 0, psize = 0;
00328
00329 av_dlog(s, "ogg_packet: curidx=%i\n", ogg->curidx);
00330
00331 do{
00332 idx = ogg->curidx;
00333
00334 while (idx < 0){
00335 ret = ogg_read_page(s, &idx);
00336 if (ret < 0)
00337 return ret;
00338 }
00339
00340 os = ogg->streams + idx;
00341
00342 av_dlog(s, "ogg_packet: idx=%d pstart=%d psize=%d segp=%d nsegs=%d\n",
00343 idx, os->pstart, os->psize, os->segp, os->nsegs);
00344
00345 if (!os->codec){
00346 if (os->header < 0){
00347 os->codec = ogg_find_codec (os->buf, os->bufpos);
00348 if (!os->codec){
00349 av_log(s, AV_LOG_WARNING, "Codec not found\n");
00350 os->header = 0;
00351 return 0;
00352 }
00353 }else{
00354 return 0;
00355 }
00356 }
00357
00358 segp = os->segp;
00359 psize = os->psize;
00360
00361 while (os->segp < os->nsegs){
00362 int ss = os->segments[os->segp++];
00363 os->psize += ss;
00364 if (ss < 255){
00365 complete = 1;
00366 break;
00367 }
00368 }
00369
00370 if (!complete && os->segp == os->nsegs){
00371 ogg->curidx = -1;
00372 os->incomplete = 1;
00373 }
00374 }while (!complete);
00375
00376 av_dlog(s, "ogg_packet: idx %i, frame size %i, start %i\n",
00377 idx, os->psize, os->pstart);
00378
00379 if (os->granule == -1)
00380 av_log(s, AV_LOG_WARNING, "Page at %"PRId64" is missing granule\n", os->page_pos);
00381
00382 ogg->curidx = idx;
00383 os->incomplete = 0;
00384
00385 if (os->header) {
00386 os->header = os->codec->header (s, idx);
00387 if (!os->header){
00388 os->segp = segp;
00389 os->psize = psize;
00390
00391
00392
00393
00394 ogg->headers = 1;
00395
00396
00397
00398 if (!s->data_offset)
00399 s->data_offset = os->sync_pos;
00400 for (i = 0; i < ogg->nstreams; i++) {
00401 struct ogg_stream *cur_os = ogg->streams + i;
00402
00403
00404
00405 if (cur_os->incomplete)
00406 s->data_offset = FFMIN(s->data_offset, cur_os->sync_pos);
00407 }
00408 }else{
00409 os->pstart += os->psize;
00410 os->psize = 0;
00411 }
00412 } else {
00413 os->pflags = 0;
00414 os->pduration = 0;
00415 if (os->codec && os->codec->packet)
00416 os->codec->packet (s, idx);
00417 if (str)
00418 *str = idx;
00419 if (dstart)
00420 *dstart = os->pstart;
00421 if (dsize)
00422 *dsize = os->psize;
00423 if (fpos)
00424 *fpos = os->sync_pos;
00425 os->pstart += os->psize;
00426 os->psize = 0;
00427 os->sync_pos = os->page_pos;
00428 }
00429
00430
00431
00432 os->page_end = 1;
00433 for (i = os->segp; i < os->nsegs; i++)
00434 if (os->segments[i] < 255) {
00435 os->page_end = 0;
00436 break;
00437 }
00438
00439 if (os->segp == os->nsegs)
00440 ogg->curidx = -1;
00441
00442 return 0;
00443 }
00444
00445 static int ogg_get_headers(AVFormatContext *s)
00446 {
00447 struct ogg *ogg = s->priv_data;
00448 int ret;
00449
00450 do{
00451 ret = ogg_packet(s, NULL, NULL, NULL, NULL);
00452 if (ret < 0)
00453 return ret;
00454 }while (!ogg->headers);
00455
00456 av_dlog(s, "found headers\n");
00457
00458 return 0;
00459 }
00460
00461 static int ogg_get_length(AVFormatContext *s)
00462 {
00463 struct ogg *ogg = s->priv_data;
00464 int i;
00465 int64_t size, end;
00466
00467 if(!s->pb->seekable)
00468 return 0;
00469
00470
00471 if (s->duration != AV_NOPTS_VALUE)
00472 return 0;
00473
00474 size = avio_size(s->pb);
00475 if(size < 0)
00476 return 0;
00477 end = size > MAX_PAGE_SIZE? size - MAX_PAGE_SIZE: 0;
00478
00479 ogg_save (s);
00480 avio_seek (s->pb, end, SEEK_SET);
00481
00482 while (!ogg_read_page (s, &i)){
00483 if (ogg->streams[i].granule != -1 && ogg->streams[i].granule != 0 &&
00484 ogg->streams[i].codec) {
00485 s->streams[i]->duration =
00486 ogg_gptopts (s, i, ogg->streams[i].granule, NULL);
00487 if (s->streams[i]->start_time != AV_NOPTS_VALUE)
00488 s->streams[i]->duration -= s->streams[i]->start_time;
00489 }
00490 }
00491
00492 ogg_restore (s, 0);
00493
00494 return 0;
00495 }
00496
00497 static int ogg_read_header(AVFormatContext *s, AVFormatParameters *ap)
00498 {
00499 struct ogg *ogg = s->priv_data;
00500 int ret, i;
00501 ogg->curidx = -1;
00502
00503 ret = ogg_get_headers(s);
00504 if (ret < 0)
00505 return ret;
00506
00507 for (i = 0; i < ogg->nstreams; i++)
00508 if (ogg->streams[i].header < 0)
00509 ogg->streams[i].codec = NULL;
00510
00511
00512 ogg_get_length (s);
00513
00514
00515 return 0;
00516 }
00517
00518 static int64_t ogg_calc_pts(AVFormatContext *s, int idx, int64_t *dts)
00519 {
00520 struct ogg *ogg = s->priv_data;
00521 struct ogg_stream *os = ogg->streams + idx;
00522 int64_t pts = AV_NOPTS_VALUE;
00523
00524 if (dts)
00525 *dts = AV_NOPTS_VALUE;
00526
00527 if (os->lastpts != AV_NOPTS_VALUE) {
00528 pts = os->lastpts;
00529 os->lastpts = AV_NOPTS_VALUE;
00530 }
00531 if (os->lastdts != AV_NOPTS_VALUE) {
00532 if (dts)
00533 *dts = os->lastdts;
00534 os->lastdts = AV_NOPTS_VALUE;
00535 }
00536 if (os->page_end) {
00537 if (os->granule != -1LL) {
00538 if (os->codec && os->codec->granule_is_start)
00539 pts = ogg_gptopts(s, idx, os->granule, dts);
00540 else
00541 os->lastpts = ogg_gptopts(s, idx, os->granule, &os->lastdts);
00542 os->granule = -1LL;
00543 }
00544 }
00545 return pts;
00546 }
00547
00548 static int ogg_read_packet(AVFormatContext *s, AVPacket *pkt)
00549 {
00550 struct ogg *ogg;
00551 struct ogg_stream *os;
00552 int idx = -1, ret;
00553 int pstart, psize;
00554 int64_t fpos, pts, dts;
00555
00556
00557 retry:
00558 do{
00559 ret = ogg_packet(s, &idx, &pstart, &psize, &fpos);
00560 if (ret < 0)
00561 return ret;
00562 }while (idx < 0 || !s->streams[idx]);
00563
00564 ogg = s->priv_data;
00565 os = ogg->streams + idx;
00566
00567
00568 pts = ogg_calc_pts(s, idx, &dts);
00569
00570 if (os->keyframe_seek && !(os->pflags & AV_PKT_FLAG_KEY))
00571 goto retry;
00572 os->keyframe_seek = 0;
00573
00574
00575 ret = av_new_packet(pkt, psize);
00576 if (ret < 0)
00577 return ret;
00578 pkt->stream_index = idx;
00579 memcpy (pkt->data, os->buf + pstart, psize);
00580
00581 pkt->pts = pts;
00582 pkt->dts = dts;
00583 pkt->flags = os->pflags;
00584 pkt->duration = os->pduration;
00585 pkt->pos = fpos;
00586
00587 return psize;
00588 }
00589
00590 static int ogg_read_close(AVFormatContext *s)
00591 {
00592 struct ogg *ogg = s->priv_data;
00593 int i;
00594
00595 for (i = 0; i < ogg->nstreams; i++){
00596 av_free (ogg->streams[i].buf);
00597 av_free (ogg->streams[i].private);
00598 }
00599 av_free (ogg->streams);
00600 return 0;
00601 }
00602
00603 static int64_t ogg_read_timestamp(AVFormatContext *s, int stream_index,
00604 int64_t *pos_arg, int64_t pos_limit)
00605 {
00606 struct ogg *ogg = s->priv_data;
00607 AVIOContext *bc = s->pb;
00608 int64_t pts = AV_NOPTS_VALUE;
00609 int i = -1;
00610 avio_seek(bc, *pos_arg, SEEK_SET);
00611 ogg_reset(ogg);
00612
00613 while (avio_tell(bc) < pos_limit && !ogg_packet(s, &i, NULL, NULL, pos_arg)) {
00614 if (i == stream_index) {
00615 struct ogg_stream *os = ogg->streams + stream_index;
00616 pts = ogg_calc_pts(s, i, NULL);
00617 if (os->keyframe_seek && !(os->pflags & AV_PKT_FLAG_KEY))
00618 pts = AV_NOPTS_VALUE;
00619 }
00620 if (pts != AV_NOPTS_VALUE)
00621 break;
00622 }
00623 ogg_reset(ogg);
00624 return pts;
00625 }
00626
00627 static int ogg_read_seek(AVFormatContext *s, int stream_index,
00628 int64_t timestamp, int flags)
00629 {
00630 struct ogg *ogg = s->priv_data;
00631 struct ogg_stream *os = ogg->streams + stream_index;
00632 int ret;
00633
00634
00635
00636 if (s->streams[stream_index]->codec->codec_type == AVMEDIA_TYPE_VIDEO
00637 && !(flags & AVSEEK_FLAG_ANY))
00638 os->keyframe_seek = 1;
00639
00640 ret = ff_seek_frame_binary(s, stream_index, timestamp, flags);
00641 os = ogg->streams + stream_index;
00642 if (ret < 0)
00643 os->keyframe_seek = 0;
00644 return ret;
00645 }
00646
00647 static int ogg_probe(AVProbeData *p)
00648 {
00649 if (!memcmp("OggS", p->buf, 5) && p->buf[5] <= 0x7)
00650 return AVPROBE_SCORE_MAX;
00651 return 0;
00652 }
00653
00654 AVInputFormat ff_ogg_demuxer = {
00655 .name = "ogg",
00656 .long_name = NULL_IF_CONFIG_SMALL("Ogg"),
00657 .priv_data_size = sizeof(struct ogg),
00658 .read_probe = ogg_probe,
00659 .read_header = ogg_read_header,
00660 .read_packet = ogg_read_packet,
00661 .read_close = ogg_read_close,
00662 .read_seek = ogg_read_seek,
00663 .read_timestamp = ogg_read_timestamp,
00664 .extensions = "ogg",
00665 .flags = AVFMT_GENERIC_INDEX,
00666 };