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