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 && | |||