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
00380
00381
00382
00383 os->incomplete = !!os->psize;
00384 }
00385 }while (!complete);
00386
00387 av_dlog(s, "ogg_packet: idx %i, frame size %i, start %i\n",
00388 idx, os->psize, os->pstart);
00389
00390 if (os->granule == -1)
00391 av_log(s, AV_LOG_WARNING, "Page at %"PRId64" is missing granule\n", os->page_pos);
00392
00393 ogg->curidx = idx;
00394 os->incomplete = 0;
00395
00396 if (os->header) {
00397 os->header = os->codec->header (s, idx);
00398 if (!os->header){
00399 os->segp = segp;
00400 os->psize = psize;
00401
00402
00403
00404
00405 ogg->headers = 1;
00406
00407
00408
00409 if (!s->data_offset)
00410 s->data_offset = os->sync_pos;
00411 for (i = 0; i < ogg->nstreams; i++) {
00412 struct ogg_stream *cur_os = ogg->streams + i;
00413
00414
00415
00416 if (cur_os->incomplete)
00417 s->data_offset = FFMIN(s->data_offset, cur_os->sync_pos);
00418 }
00419 }else{
00420 os->pstart += os->psize;
00421 os->psize = 0;
00422 }
00423 } else {
00424 os->pflags = 0;
00425 os->pduration = 0;
00426 if (os->codec && os->codec->packet)
00427 os->codec->packet (s, idx);
00428 if (str)
00429 *str = idx;
00430 if (dstart)
00431 *dstart = os->pstart;
00432 if (dsize)
00433 *dsize = os->psize;
00434 if (fpos)
00435 *fpos = os->sync_pos;
00436 os->pstart += os->psize;
00437 os->psize = 0;
00438 os->sync_pos = os->page_pos;
00439 }
00440
00441
00442
00443 os->page_end = 1;
00444 for (i = os->segp; i < os->nsegs; i++)
00445 if (os->segments[i] < 255) {
00446 os->page_end = 0;
00447 break;
00448 }
00449
00450 if (os->segp == os->nsegs)
00451 ogg->curidx = -1;
00452
00453 return 0;
00454 }
00455
00456 static int ogg_get_headers(AVFormatContext *s)
00457 {
00458 struct ogg *ogg = s->priv_data;
00459 int ret;
00460
00461 do{
00462 ret = ogg_packet(s, NULL, NULL, NULL, NULL);
00463 if (ret < 0)
00464 return ret;
00465 }while (!ogg->headers);
00466
00467 av_dlog(s, "found headers\n");
00468
00469 return 0;
00470 }
00471
00472 static int ogg_get_length(AVFormatContext *s)
00473 {
00474 struct ogg *ogg = s->priv_data;
00475 int i;
00476 int64_t size, end;
00477
00478 if(!s->pb->seekable)
00479 return 0;
00480
00481
00482 if (s->duration != AV_NOPTS_VALUE)
00483 return 0;
00484
00485 size = avio_size(s->pb);
00486 if(size < 0)
00487 return 0;
00488 end = size > MAX_PAGE_SIZE? size - MAX_PAGE_SIZE: 0;
00489
00490 ogg_save (s);
00491 avio_seek (s->pb, end, SEEK_SET);
00492
00493 while (!ogg_read_page (s, &i)){
00494 if (ogg->streams[i].granule != -1 && ogg->streams[i].granule != 0 &&
00495 ogg->streams[i].codec) {
00496 s->streams[i]->duration =
00497 ogg_gptopts (s, i, ogg->streams[i].granule, NULL);
00498 if (s->streams[i]->start_time != AV_NOPTS_VALUE)
00499 s->streams[i]->duration -= s->streams[i]->start_time;
00500 }
00501 }
00502
00503 ogg_restore (s, 0);
00504
00505 return 0;
00506 }
00507
00508 static int ogg_read_close(AVFormatContext *s)
00509 {
00510 struct ogg *ogg = s->priv_data;
00511 int i;
00512
00513 for (i = 0; i < ogg->nstreams; i++) {
00514 av_free(ogg->streams[i].buf);
00515 if (ogg->streams[i].codec &&
00516 ogg->streams[i].codec->cleanup) {
00517 ogg->streams[i].codec->cleanup(s, i);
00518 }
00519 av_free(ogg->streams[i].private);
00520 }
00521 av_free(ogg->streams);
00522 return 0;
00523 }
00524
00525 static int ogg_read_header(AVFormatContext *s)
00526 {
00527 struct ogg *ogg = s->priv_data;
00528 int ret, i;
00529 ogg->curidx = -1;
00530
00531 ret = ogg_get_headers(s);
00532 if (ret < 0) {
00533 ogg_read_close(s);
00534 return ret;
00535 }
00536
00537 for (i = 0; i < ogg->nstreams; i++)
00538 if (ogg->streams[i].header < 0)
00539 ogg->streams[i].codec = NULL;
00540
00541
00542 ogg_get_length (s);
00543
00544
00545 return 0;
00546 }
00547
00548 static int64_t ogg_calc_pts(AVFormatContext *s, int idx, int64_t *dts)
00549 {
00550 struct ogg *ogg = s->priv_data;
00551 struct ogg_stream *os = ogg->streams + idx;
00552 int64_t pts = AV_NOPTS_VALUE;
00553
00554 if (dts)
00555 *dts = AV_NOPTS_VALUE;
00556
00557 if (os->lastpts != AV_NOPTS_VALUE) {
00558 pts = os->lastpts;
00559 os->lastpts = AV_NOPTS_VALUE;
00560 }
00561 if (os->lastdts != AV_NOPTS_VALUE) {
00562 if (dts)
00563 *dts = os->lastdts;
00564 os->lastdts = AV_NOPTS_VALUE;
00565 }
00566 if (os->page_end) {
00567 if (os->granule != -1LL) {
00568 if (os->codec && os->codec->granule_is_start)
00569 pts = ogg_gptopts(s, idx, os->granule, dts);
00570 else
00571 os->lastpts = ogg_gptopts(s, idx, os->granule, &os->lastdts);
00572 os->granule = -1LL;
00573 }
00574 }
00575 return pts;
00576 }
00577
00578 static int ogg_read_packet(AVFormatContext *s, AVPacket *pkt)
00579 {
00580 struct ogg *ogg;
00581 struct ogg_stream *os;
00582 int idx = -1, ret;
00583 int pstart, psize;
00584 int64_t fpos, pts, dts;
00585
00586
00587 retry:
00588 do{
00589 ret = ogg_packet(s, &idx, &pstart, &psize, &fpos);
00590 if (ret < 0)
00591 return ret;
00592 }while (idx < 0 || !s->streams[idx]);
00593
00594 ogg = s->priv_data;
00595 os = ogg->streams + idx;
00596
00597
00598 pts = ogg_calc_pts(s, idx, &dts);
00599
00600 if (os->keyframe_seek && !(os->pflags & AV_PKT_FLAG_KEY))
00601 goto retry;
00602 os->keyframe_seek = 0;
00603
00604
00605 ret = av_new_packet(pkt, psize);
00606 if (ret < 0)
00607 return ret;
00608 pkt->stream_index = idx;
00609 memcpy (pkt->data, os->buf + pstart, psize);
00610
00611 pkt->pts = pts;
00612 pkt->dts = dts;
00613 pkt->flags = os->pflags;
00614 pkt->duration = os->pduration;
00615 pkt->pos = fpos;
00616
00617 return psize;
00618 }
00619
00620 static int64_t ogg_read_timestamp(AVFormatContext *s, int stream_index,
00621 int64_t *pos_arg, int64_t pos_limit)
00622 {
00623 struct ogg *ogg = s->priv_data;
00624 AVIOContext *bc = s->pb;
00625 int64_t pts = AV_NOPTS_VALUE;
00626 int i = -1;
00627 avio_seek(bc, *pos_arg, SEEK_SET);
00628 ogg_reset(ogg);
00629
00630 while (avio_tell(bc) < pos_limit && !ogg_packet(s, &i, NULL, NULL, pos_arg)) {
00631 if (i == stream_index) {
00632 struct ogg_stream *os = ogg->streams + stream_index;
00633 pts = ogg_calc_pts(s, i, NULL);
00634 if (os->keyframe_seek && !(os->pflags & AV_PKT_FLAG_KEY))
00635 pts = AV_NOPTS_VALUE;
00636 }
00637 if (pts != AV_NOPTS_VALUE)
00638 break;
00639 }
00640 ogg_reset(ogg);
00641 return pts;
00642 }
00643
00644 static int ogg_read_seek(AVFormatContext *s, int stream_index,
00645 int64_t timestamp, int flags)
00646 {
00647 struct ogg *ogg = s->priv_data;
00648 struct ogg_stream *os = ogg->streams + stream_index;
00649 int ret;
00650
00651
00652
00653 if (s->streams[stream_index]->codec->codec_type == AVMEDIA_TYPE_VIDEO
00654 && !(flags & AVSEEK_FLAG_ANY))
00655 os->keyframe_seek = 1;
00656
00657 ret = ff_seek_frame_binary(s, stream_index, timestamp, flags);
00658 os = ogg->streams + stream_index;
00659 if (ret < 0)
00660 os->keyframe_seek = 0;
00661 return ret;
00662 }
00663
00664 static int ogg_probe(AVProbeData *p)
00665 {
00666 if (!memcmp("OggS", p->buf, 5) && p->buf[5] <= 0x7)
00667 return AVPROBE_SCORE_MAX;
00668 return 0;
00669 }
00670
00671 AVInputFormat ff_ogg_demuxer = {
00672 .name = "ogg",
00673 .long_name = NULL_IF_CONFIG_SMALL("Ogg"),
00674 .priv_data_size = sizeof(struct ogg),
00675 .read_probe = ogg_probe,
00676 .read_header = ogg_read_header,
00677 .read_packet = ogg_read_packet,
00678 .read_close = ogg_read_close,
00679 .read_seek = ogg_read_seek,
00680 .read_timestamp = ogg_read_timestamp,
00681 .extensions = "ogg",
00682 .flags = AVFMT_GENERIC_INDEX,
00683 };