OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Ogg bitstream support | 2 * Ogg bitstream support |
3 * Luca Barbato <lu_zero@gentoo.org> | 3 * Luca Barbato <lu_zero@gentoo.org> |
4 * Based on tcvp implementation | 4 * Based on tcvp implementation |
5 */ | 5 */ |
6 | 6 |
7 /* | 7 /* |
8 Copyright (C) 2005 Michael Ahlberg, Måns Rullgård | 8 Copyright (C) 2005 Michael Ahlberg, Måns Rullgård |
9 | 9 |
10 Permission is hereby granted, free of charge, to any person | 10 Permission is hereby granted, free of charge, to any person |
(...skipping 21 matching lines...) Expand all Loading... | |
32 #include "oggdec.h" | 32 #include "oggdec.h" |
33 #include "avformat.h" | 33 #include "avformat.h" |
34 #include "internal.h" | 34 #include "internal.h" |
35 #include "vorbiscomment.h" | 35 #include "vorbiscomment.h" |
36 | 36 |
37 #define MAX_PAGE_SIZE 65307 | 37 #define MAX_PAGE_SIZE 65307 |
38 #define DECODER_BUFFER_SIZE MAX_PAGE_SIZE | 38 #define DECODER_BUFFER_SIZE MAX_PAGE_SIZE |
39 | 39 |
40 static const struct ogg_codec * const ogg_codecs[] = { | 40 static const struct ogg_codec * const ogg_codecs[] = { |
41 &ff_skeleton_codec, | 41 &ff_skeleton_codec, |
42 #if CONFIG_DIRAC_DEMUXER | |
42 &ff_dirac_codec, | 43 &ff_dirac_codec, |
44 #endif | |
45 #if CONFIG_LIBSPEEX | |
43 &ff_speex_codec, | 46 &ff_speex_codec, |
47 #endif | |
44 &ff_vorbis_codec, | 48 &ff_vorbis_codec, |
45 &ff_theora_codec, | 49 &ff_theora_codec, |
50 #if CONFIG_FLAC_DECODER | |
46 &ff_flac_codec, | 51 &ff_flac_codec, |
52 #endif | |
47 &ff_celt_codec, | 53 &ff_celt_codec, |
54 #if CONFIG_DIRAC_DEMUXER | |
48 &ff_old_dirac_codec, | 55 &ff_old_dirac_codec, |
56 #endif | |
57 #if CONFIG_FLAC_DECODER | |
49 &ff_old_flac_codec, | 58 &ff_old_flac_codec, |
59 #endif | |
50 &ff_ogm_video_codec, | 60 &ff_ogm_video_codec, |
51 &ff_ogm_audio_codec, | 61 &ff_ogm_audio_codec, |
52 &ff_ogm_text_codec, | 62 &ff_ogm_text_codec, |
53 &ff_ogm_old_codec, | 63 &ff_ogm_old_codec, |
54 NULL | 64 NULL |
55 }; | 65 }; |
56 | 66 |
57 //FIXME We could avoid some structure duplication | 67 //FIXME We could avoid some structure duplication |
58 static int ogg_save(AVFormatContext *s) | 68 static int ogg_save(AVFormatContext *s) |
59 { | 69 { |
(...skipping 428 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
488 s->streams[i]->duration -= s->streams[i]->start_time; | 498 s->streams[i]->duration -= s->streams[i]->start_time; |
489 streams_left-= (ogg->streams[i].got_start==-1); | 499 streams_left-= (ogg->streams[i].got_start==-1); |
490 ogg->streams[i].got_start= 1; | 500 ogg->streams[i].got_start= 1; |
491 }else if(!ogg->streams[i].got_start){ | 501 }else if(!ogg->streams[i].got_start){ |
492 ogg->streams[i].got_start= -1; | 502 ogg->streams[i].got_start= -1; |
493 streams_left++; | 503 streams_left++; |
494 } | 504 } |
495 } | 505 } |
496 } | 506 } |
497 | 507 |
498 ogg_restore (s, 0); | 508 ogg_restore (s, 0); |
DaleCurtis
2012/02/04 18:06:20
Applied 35_oggdec_duration.patch, despite upstream
scherkus (not reviewing)
2012/02/06 17:46:29
We should sanity check those tests for accuracy as
DaleCurtis
2012/02/06 18:59:01
Without this patch it gets the duration wrong by >
| |
499 | 509 |
500 ogg_save (s); | |
501 avio_seek (s->pb, 0, SEEK_SET); | |
502 while (!ogg_read_page (s, &i)){ | |
503 if (ogg->streams[i].granule != -1 && ogg->streams[i].granule != 0 && | |
504 ogg->streams[i].codec) { | |
505 if(s->streams[i]->duration && s->streams[i]->start_time == AV_NOPTS_ VALUE && !ogg->streams[i].got_start){ | |
506 int64_t start= ogg_gptopts (s, i, ogg->streams[i].granule, NULL) ; | |
507 if(av_rescale_q(start, s->streams[i]->time_base, AV_TIME_BASE_Q) > AV_TIME_BASE) | |
508 s->streams[i]->duration -= start; | |
509 ogg->streams[i].got_start= 1; | |
510 streams_left--; | |
511 } | |
512 if(streams_left<=0) | |
513 break; | |
514 } | |
515 } | |
516 ogg_restore (s, 0); | |
517 | |
518 return 0; | 510 return 0; |
519 } | 511 } |
520 | 512 |
521 static int ogg_read_header(AVFormatContext *s) | 513 static int ogg_read_header(AVFormatContext *s) |
522 { | 514 { |
523 struct ogg *ogg = s->priv_data; | 515 struct ogg *ogg = s->priv_data; |
524 int ret, i; | 516 int ret, i; |
525 ogg->curidx = -1; | 517 ogg->curidx = -1; |
526 //linear headers seek from start | 518 //linear headers seek from start |
527 ret = ogg_get_headers(s); | 519 ret = ogg_get_headers(s); |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
624 return 0; | 616 return 0; |
625 } | 617 } |
626 | 618 |
627 static int64_t ogg_read_timestamp(AVFormatContext *s, int stream_index, | 619 static int64_t ogg_read_timestamp(AVFormatContext *s, int stream_index, |
628 int64_t *pos_arg, int64_t pos_limit) | 620 int64_t *pos_arg, int64_t pos_limit) |
629 { | 621 { |
630 struct ogg *ogg = s->priv_data; | 622 struct ogg *ogg = s->priv_data; |
631 AVIOContext *bc = s->pb; | 623 AVIOContext *bc = s->pb; |
632 int64_t pts = AV_NOPTS_VALUE; | 624 int64_t pts = AV_NOPTS_VALUE; |
633 int i = -1; | 625 int i = -1; |
626 int packet = 0; | |
627 int64_t start_pos = *pos_arg; | |
634 avio_seek(bc, *pos_arg, SEEK_SET); | 628 avio_seek(bc, *pos_arg, SEEK_SET); |
635 ogg_reset(ogg); | 629 ogg_reset(ogg); |
636 | 630 |
637 while (avio_tell(bc) < pos_limit && !ogg_packet(s, &i, NULL, NULL, pos_arg)) { | 631 while (avio_tell(bc) < pos_limit && !ogg_packet(s, &i, NULL, NULL, pos_arg)) { |
638 if (i == stream_index) { | 632 if (i == stream_index) { |
639 struct ogg_stream *os = ogg->streams + stream_index; | 633 struct ogg_stream *os = ogg->streams + stream_index; |
640 pts = ogg_calc_pts(s, i, NULL); | 634 pts = ogg_calc_pts(s, i, NULL); |
641 if (os->keyframe_seek && !(os->pflags & AV_PKT_FLAG_KEY)) | 635 if (os->keyframe_seek && !(os->pflags & AV_PKT_FLAG_KEY)) |
642 pts = AV_NOPTS_VALUE; | 636 pts = AV_NOPTS_VALUE; |
637 | |
638 // This is for the special case for the first packet in the stream. | |
639 if (pts == AV_NOPTS_VALUE && start_pos <= s->data_offset && !packet) { | |
640 pts = 0; | |
641 } | |
642 ++packet; | |
643 } | 643 } |
644 if (pts != AV_NOPTS_VALUE) | 644 if (pts != AV_NOPTS_VALUE) |
645 break; | 645 break; |
646 } | 646 } |
647 ogg_reset(ogg); | 647 ogg_reset(ogg); |
648 return pts; | 648 return pts; |
649 } | 649 } |
650 | 650 |
651 static int ogg_read_seek(AVFormatContext *s, int stream_index, | 651 static int ogg_read_seek(AVFormatContext *s, int stream_index, |
652 int64_t timestamp, int flags) | 652 int64_t timestamp, int flags) |
653 { | 653 { |
654 struct ogg *ogg = s->priv_data; | 654 struct ogg *ogg = s->priv_data; |
655 struct ogg_stream *os = ogg->streams + stream_index; | 655 struct ogg_stream *os = ogg->streams + stream_index; |
656 int ret; | 656 int ret; |
657 int64_t seek_pos; | |
658 int64_t pos_arg; | |
659 int64_t seek_pts; | |
660 int i; | |
657 | 661 |
658 // Try seeking to a keyframe first. If this fails (very possible), | 662 // Try seeking to a keyframe first. If this fails (very possible), |
659 // av_seek_frame will fall back to ignoring keyframes | 663 // av_seek_frame will fall back to ignoring keyframes |
660 if (s->streams[stream_index]->codec->codec_type == AVMEDIA_TYPE_VIDEO | 664 if (s->streams[stream_index]->codec->codec_type == AVMEDIA_TYPE_VIDEO |
661 && !(flags & AVSEEK_FLAG_ANY)) | 665 && !(flags & AVSEEK_FLAG_ANY)) |
662 os->keyframe_seek = 1; | 666 os->keyframe_seek = 1; |
663 | 667 |
664 ret = ff_seek_frame_binary(s, stream_index, timestamp, flags); | 668 ret = ff_seek_frame_binary(s, stream_index, timestamp, flags); |
665 os = ogg->streams + stream_index; | 669 os = ogg->streams + stream_index; |
666 if (ret < 0) | 670 if (ret < 0) |
667 os->keyframe_seek = 0; | 671 os->keyframe_seek = 0; |
672 | |
673 // Save the position seeked to. | |
674 pos_arg = seek_pos = avio_tell(s->pb); | |
DaleCurtis
2012/02/04 18:06:20
Patch required swapping url_ftell w/ avio_tell.
scherkus (not reviewing)
2012/02/06 17:46:29
For these function swaps is it because the patch w
DaleCurtis
2012/02/06 18:59:01
Yes.
| |
675 seek_pts = ogg_read_timestamp(s, stream_index, &pos_arg, avio_size(s->pb)); | |
DaleCurtis
2012/02/04 18:06:20
Patch required swapping url_fsize w/ avio_size.
| |
676 os = ogg->streams + stream_index; | |
677 | |
678 // Since we have seeked to the beginning then reset lastpts and lastdts to 0 . | |
679 if (!seek_pts) { | |
680 for (i = 0; i < ogg->nstreams; i++){ | |
681 struct ogg_stream *stream = ogg->streams + i; | |
682 stream->lastpts = 0; | |
683 stream->lastdts = 0; | |
684 } | |
685 os->keyframe_seek = 0; | |
686 } | |
687 avio_seek(s->pb, seek_pos, SEEK_SET); | |
DaleCurtis
2012/02/04 18:06:20
Patch required swapping url_fseek w/ avio_seek.
| |
668 return ret; | 688 return ret; |
669 } | 689 } |
670 | 690 |
671 static int ogg_probe(AVProbeData *p) | 691 static int ogg_probe(AVProbeData *p) |
672 { | 692 { |
673 if (!memcmp("OggS", p->buf, 5) && p->buf[5] <= 0x7) | 693 if (!memcmp("OggS", p->buf, 5) && p->buf[5] <= 0x7) |
674 return AVPROBE_SCORE_MAX; | 694 return AVPROBE_SCORE_MAX; |
675 return 0; | 695 return 0; |
676 } | 696 } |
677 | 697 |
678 AVInputFormat ff_ogg_demuxer = { | 698 AVInputFormat ff_ogg_demuxer = { |
679 .name = "ogg", | 699 .name = "ogg", |
680 .long_name = NULL_IF_CONFIG_SMALL("Ogg"), | 700 .long_name = NULL_IF_CONFIG_SMALL("Ogg"), |
681 .priv_data_size = sizeof(struct ogg), | 701 .priv_data_size = sizeof(struct ogg), |
682 .read_probe = ogg_probe, | 702 .read_probe = ogg_probe, |
683 .read_header = ogg_read_header, | 703 .read_header = ogg_read_header, |
684 .read_packet = ogg_read_packet, | 704 .read_packet = ogg_read_packet, |
685 .read_close = ogg_read_close, | 705 .read_close = ogg_read_close, |
686 .read_seek = ogg_read_seek, | 706 .read_seek = ogg_read_seek, |
687 .read_timestamp = ogg_read_timestamp, | 707 .read_timestamp = ogg_read_timestamp, |
688 .extensions = "ogg", | 708 .extensions = "ogg", |
689 .flags = AVFMT_GENERIC_INDEX, | 709 .flags = AVFMT_GENERIC_INDEX, |
690 }; | 710 }; |
OLD | NEW |