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 av_free(ogg->streams[i].private);
00512 }
00513 av_free(ogg->streams);
00514 return 0;
00515 }
00516
00517 static int ogg_read_header(AVFormatContext *s)
00518 {
00519 struct ogg *ogg = s->priv_data;
00520 int ret, i;
00521 ogg->curidx = -1;
00522
00523 ret = ogg_get_headers(s);
00524 if (ret < 0) {
00525 ogg_read_close(s);
00526 return ret;
00527 }
00528
00529 for (i = 0; i < ogg->nstreams; i++)
00530 if (ogg->streams[i].header < 0)
00531 ogg->streams[i].codec = NULL;
00532
00533
00534 ogg_get_length (s);
00535
00536
00537 return 0;
00538 }
00539
00540 static int64_t ogg_calc_pts(AVFormatContext *s, int idx, int64_t *dts)
00541 {
00542 struct ogg *ogg = s->priv_data;
00543 struct ogg_stream *os = ogg->streams + idx;
00544 int64_t pts = AV_NOPTS_VALUE;
00545
00546 if (dts)
00547 *dts = AV_NOPTS_VALUE;
00548
00549 if (os->lastpts != AV_NOPTS_VALUE) {
00550 pts = os->lastpts;
00551 os->lastpts = AV_NOPTS_VALUE;
00552 }
00553 if (os->lastdts != AV_NOPTS_VALUE) {
00554 if (dts)
00555 *dts = os->lastdts;
00556 os->lastdts = AV_NOPTS_VALUE;
00557 }
00558 if (os->page_end) {
00559 if (os->granule != -1LL) {
00560 if (os->codec && os->codec->granule_is_start)
00561 pts = ogg_gptopts(s, idx, os->granule, dts);
00562 else
00563 os->lastpts = ogg_gptopts(s, idx, os->granule, &os->lastdts);
00564 os->granule = -1LL;
00565 }
00566 }
00567 return pts;
00568 }
00569
00570 static int ogg_read_packet(AVFormatContext *s, AVPacket *pkt)
00571 {
00572 struct ogg *ogg;
00573 struct ogg_stream *os;
00574 int idx = -1, ret;
00575 int pstart, psize;
00576 int64_t fpos, pts, dts;
00577
00578
00579 retry:
00580 do{
00581 ret = ogg_packet(s, &idx, &pstart, &psize, &fpos);
00582 if (ret < 0)
00583 return ret;
00584 }while (idx < 0 || !s->streams[idx]);
00585
00586 ogg = s->priv_data;
00587 os = ogg->streams + idx;
00588
00589
00590 pts = ogg_calc_pts(s, idx, &dts);
00591
00592 if (os->keyframe_seek && !(os->pflags & AV_PKT_FLAG_KEY))
00593 goto retry;
00594 os->keyframe_seek = 0;
00595
00596
00597 ret = av_new_packet(pkt, psize);
00598 if (ret < 0)
00599 return ret;
00600 pkt->stream_index = idx;
00601 memcpy (pkt->data, os->buf + pstart, psize);
00602
00603 pkt->pts = pts;
00604 pkt->dts = dts;
00605 pkt->flags = os->pflags;
00606 pkt->duration = os->pduration;
00607 pkt->pos = fpos;
00608
00609 return psize;
00610 }
00611
00612 static int64_t ogg_read_timestamp(AVFormatContext *s, int stream_index,
00613 int64_t *pos_arg, int64_t pos_limit)
00614 {
00615 struct ogg *ogg = s->priv_data;
00616 AVIOContext *bc = s->pb;
00617 int64_t pts = AV_NOPTS_VALUE;
00618 int i = -1;
00619 avio_seek(bc, *pos_arg, SEEK_SET);
00620 ogg_reset(ogg);
00621
00622 while (avio_tell(bc) < pos_limit && !ogg_packet(s, &i, NULL, NULL, pos_arg)) {
00623 if (i == stream_index) {
00624 struct ogg_stream *os = ogg->streams + stream_index;
00625 pts = ogg_calc_pts(s, i, NULL);
00626 if (os->keyframe_seek && !(os->pflags & AV_PKT_FLAG_KEY))
00627 pts = AV_NOPTS_VALUE;
00628 }
00629 if (pts != AV_NOPTS_VALUE)
00630 break;
00631 }
00632 ogg_reset(ogg);
00633 return pts;
00634 }
00635
00636 static int ogg_read_seek(AVFormatContext *s, int stream_index,
00637 int64_t timestamp, int flags)
00638 {
00639 struct ogg *ogg = s->priv_data;
00640 struct ogg_stream *os = ogg->streams + stream_index;
00641 int ret;
00642
00643
00644
00645 if (s->streams[stream_index]->codec->codec_type == AVMEDIA_TYPE_VIDEO
00646 && !(flags & AVSEEK_FLAG_ANY))
00647 os->keyframe_seek = 1;
00648
00649 ret = ff_seek_frame_binary(s, stream_index, timestamp, flags);
00650 os = ogg->streams + stream_index;
00651 if (ret < 0)
00652 os->keyframe_seek = 0;
00653 return ret;
00654 }
00655
00656 static int ogg_probe(AVProbeData *p)
00657 {
00658 if (!memcmp("OggS", p->buf, 5) && p->buf[5] <= 0x7)
00659 return AVPROBE_SCORE_MAX;
00660 return 0;
00661 }
00662
00663 AVInputFormat ff_ogg_demuxer = {
00664 .name = "ogg",
00665 .long_name = NULL_IF_CONFIG_SMALL("Ogg"),
00666 .priv_data_size = sizeof(struct ogg),
00667 .read_probe = ogg_probe,
00668 .read_header = ogg_read_header,
00669 .read_packet = ogg_read_packet,
00670 .read_close = ogg_read_close,
00671 .read_seek = ogg_read_seek,
00672 .read_timestamp = ogg_read_timestamp,
00673 .extensions = "ogg",
00674 .flags = AVFMT_GENERIC_INDEX,
00675 };