Fixes issue251 Originally committed as revision 20815 to svn://svn.ffmpeg.org/ffmpeg/trunktags/v0.6
| @@ -116,7 +116,7 @@ ogg_reset (struct ogg * ogg) | |||
| os->pstart = 0; | |||
| os->psize = 0; | |||
| os->granule = -1; | |||
| os->lastgp = -1; | |||
| os->lastpts = AV_NOPTS_VALUE; | |||
| os->nsegs = 0; | |||
| os->segp = 0; | |||
| } | |||
| @@ -288,7 +288,6 @@ ogg_read_page (AVFormatContext * s, int *str) | |||
| if (get_buffer (bc, os->buf + os->bufpos, size) < size) | |||
| return -1; | |||
| os->lastgp = os->granule; | |||
| os->bufpos += size; | |||
| os->granule = gp; | |||
| os->flags = flags; | |||
| @@ -303,7 +302,7 @@ static int | |||
| ogg_packet (AVFormatContext * s, int *str, int *dstart, int *dsize) | |||
| { | |||
| struct ogg *ogg = s->priv_data; | |||
| int idx; | |||
| int idx, i; | |||
| struct ogg_stream *os; | |||
| int complete = 0; | |||
| int segp = 0, psize = 0; | |||
| @@ -393,6 +392,15 @@ ogg_packet (AVFormatContext * s, int *str, int *dstart, int *dsize) | |||
| os->psize = 0; | |||
| } | |||
| // determine whether there are more complete packets in this page | |||
| // if not, the page's granule will apply to this packet | |||
| os->page_end = 1; | |||
| for (i = os->segp; i < os->nsegs; i++) | |||
| if (os->segments[i] < 255) { | |||
| os->page_end = 0; | |||
| break; | |||
| } | |||
| os->seq++; | |||
| if (os->segp == os->nsegs) | |||
| ogg->curidx = -1; | |||
| @@ -519,9 +527,20 @@ ogg_read_packet (AVFormatContext * s, AVPacket * pkt) | |||
| return AVERROR(EIO); | |||
| pkt->stream_index = idx; | |||
| memcpy (pkt->data, os->buf + pstart, psize); | |||
| if (os->lastgp != -1LL){ | |||
| pkt->pts = ogg_gptopts (s, idx, os->lastgp); | |||
| os->lastgp = -1; | |||
| if (os->lastpts != AV_NOPTS_VALUE) { | |||
| pkt->pts = os->lastpts; | |||
| os->lastpts = AV_NOPTS_VALUE; | |||
| } | |||
| if (os->page_end) { | |||
| if (os->granule != -1LL) { | |||
| if (os->codec && os->codec->granule_is_start) | |||
| pkt->pts = ogg_gptopts(s, idx, os->granule); | |||
| else | |||
| os->lastpts = ogg_gptopts(s, idx, os->granule); | |||
| os->granule = -1LL; | |||
| } else | |||
| av_log(s, AV_LOG_WARNING, "Packet is missing granule\n"); | |||
| } | |||
| pkt->flags = os->pflags; | |||
| @@ -41,6 +41,11 @@ struct ogg_codec { | |||
| int (*header)(AVFormatContext *, int); | |||
| int (*packet)(AVFormatContext *, int); | |||
| uint64_t (*gptopts)(AVFormatContext *, int, uint64_t); | |||
| /** | |||
| * 1 if granule is the start time of the associated packet. | |||
| * 0 if granule is the end time of the associated packet. | |||
| */ | |||
| int granule_is_start; | |||
| }; | |||
| struct ogg_stream { | |||
| @@ -53,12 +58,14 @@ struct ogg_stream { | |||
| unsigned int pduration; | |||
| uint32_t serial; | |||
| uint32_t seq; | |||
| uint64_t granule, lastgp; | |||
| uint64_t granule; | |||
| int64_t lastpts; | |||
| int flags; | |||
| const struct ogg_codec *codec; | |||
| int header; | |||
| int nsegs, segp; | |||
| uint8_t segments[255]; | |||
| int page_end; ///< current packet is the last one completed in the page | |||
| void *private; | |||
| }; | |||
| @@ -153,26 +153,30 @@ const struct ogg_codec ff_ogm_video_codec = { | |||
| .magic = "\001video", | |||
| .magicsize = 6, | |||
| .header = ogm_header, | |||
| .packet = ogm_packet | |||
| .packet = ogm_packet, | |||
| .granule_is_start = 1, | |||
| }; | |||
| const struct ogg_codec ff_ogm_audio_codec = { | |||
| .magic = "\001audio", | |||
| .magicsize = 6, | |||
| .header = ogm_header, | |||
| .packet = ogm_packet | |||
| .packet = ogm_packet, | |||
| .granule_is_start = 1, | |||
| }; | |||
| const struct ogg_codec ff_ogm_text_codec = { | |||
| .magic = "\001text", | |||
| .magicsize = 5, | |||
| .header = ogm_header, | |||
| .packet = ogm_packet | |||
| .packet = ogm_packet, | |||
| .granule_is_start = 1, | |||
| }; | |||
| const struct ogg_codec ff_ogm_old_codec = { | |||
| .magic = "\001Direct Show Samples embedded in Ogg", | |||
| .magicsize = 35, | |||
| .header = ogm_dshow_header, | |||
| .packet = ogm_packet | |||
| .packet = ogm_packet, | |||
| .granule_is_start = 1, | |||
| }; | |||
| @@ -95,15 +95,16 @@ static int speex_packet(AVFormatContext *s, int idx) | |||
| os->private = spxp; | |||
| } | |||
| if (os->flags & OGG_FLAG_EOS && os->lastgp != -1 && os->granule > 0) { | |||
| if (os->flags & OGG_FLAG_EOS && os->lastpts != AV_NOPTS_VALUE && | |||
| os->granule > 0) { | |||
| /* first packet of final page. we have to calculate the final packet | |||
| duration here because it is the only place we know the next-to-last | |||
| granule position. */ | |||
| spxp->final_packet_duration = os->granule - os->lastgp - | |||
| spxp->final_packet_duration = os->granule - os->lastpts - | |||
| packet_size * (ogg_page_packets(os) - 1); | |||
| } | |||
| if (!os->lastgp && os->granule > 0) | |||
| if (!os->lastpts && os->granule > 0) | |||
| /* first packet */ | |||
| os->pduration = os->granule - packet_size * (ogg_page_packets(os) - 1); | |||
| else if (os->flags & OGG_FLAG_EOS && os->segp == os->nsegs && | |||