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->pstart = 0; | ||||
os->psize = 0; | os->psize = 0; | ||||
os->granule = -1; | os->granule = -1; | ||||
os->lastgp = -1; | |||||
os->lastpts = AV_NOPTS_VALUE; | |||||
os->nsegs = 0; | os->nsegs = 0; | ||||
os->segp = 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) | if (get_buffer (bc, os->buf + os->bufpos, size) < size) | ||||
return -1; | return -1; | ||||
os->lastgp = os->granule; | |||||
os->bufpos += size; | os->bufpos += size; | ||||
os->granule = gp; | os->granule = gp; | ||||
os->flags = flags; | os->flags = flags; | ||||
@@ -303,7 +302,7 @@ static int | |||||
ogg_packet (AVFormatContext * s, int *str, int *dstart, int *dsize) | ogg_packet (AVFormatContext * s, int *str, int *dstart, int *dsize) | ||||
{ | { | ||||
struct ogg *ogg = s->priv_data; | struct ogg *ogg = s->priv_data; | ||||
int idx; | |||||
int idx, i; | |||||
struct ogg_stream *os; | struct ogg_stream *os; | ||||
int complete = 0; | int complete = 0; | ||||
int segp = 0, psize = 0; | int segp = 0, psize = 0; | ||||
@@ -393,6 +392,15 @@ ogg_packet (AVFormatContext * s, int *str, int *dstart, int *dsize) | |||||
os->psize = 0; | 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++; | os->seq++; | ||||
if (os->segp == os->nsegs) | if (os->segp == os->nsegs) | ||||
ogg->curidx = -1; | ogg->curidx = -1; | ||||
@@ -519,9 +527,20 @@ ogg_read_packet (AVFormatContext * s, AVPacket * pkt) | |||||
return AVERROR(EIO); | return AVERROR(EIO); | ||||
pkt->stream_index = idx; | pkt->stream_index = idx; | ||||
memcpy (pkt->data, os->buf + pstart, psize); | 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; | pkt->flags = os->pflags; | ||||
@@ -41,6 +41,11 @@ struct ogg_codec { | |||||
int (*header)(AVFormatContext *, int); | int (*header)(AVFormatContext *, int); | ||||
int (*packet)(AVFormatContext *, int); | int (*packet)(AVFormatContext *, int); | ||||
uint64_t (*gptopts)(AVFormatContext *, int, uint64_t); | 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 { | struct ogg_stream { | ||||
@@ -53,12 +58,14 @@ struct ogg_stream { | |||||
unsigned int pduration; | unsigned int pduration; | ||||
uint32_t serial; | uint32_t serial; | ||||
uint32_t seq; | uint32_t seq; | ||||
uint64_t granule, lastgp; | |||||
uint64_t granule; | |||||
int64_t lastpts; | |||||
int flags; | int flags; | ||||
const struct ogg_codec *codec; | const struct ogg_codec *codec; | ||||
int header; | int header; | ||||
int nsegs, segp; | int nsegs, segp; | ||||
uint8_t segments[255]; | uint8_t segments[255]; | ||||
int page_end; ///< current packet is the last one completed in the page | |||||
void *private; | void *private; | ||||
}; | }; | ||||
@@ -153,26 +153,30 @@ const struct ogg_codec ff_ogm_video_codec = { | |||||
.magic = "\001video", | .magic = "\001video", | ||||
.magicsize = 6, | .magicsize = 6, | ||||
.header = ogm_header, | .header = ogm_header, | ||||
.packet = ogm_packet | |||||
.packet = ogm_packet, | |||||
.granule_is_start = 1, | |||||
}; | }; | ||||
const struct ogg_codec ff_ogm_audio_codec = { | const struct ogg_codec ff_ogm_audio_codec = { | ||||
.magic = "\001audio", | .magic = "\001audio", | ||||
.magicsize = 6, | .magicsize = 6, | ||||
.header = ogm_header, | .header = ogm_header, | ||||
.packet = ogm_packet | |||||
.packet = ogm_packet, | |||||
.granule_is_start = 1, | |||||
}; | }; | ||||
const struct ogg_codec ff_ogm_text_codec = { | const struct ogg_codec ff_ogm_text_codec = { | ||||
.magic = "\001text", | .magic = "\001text", | ||||
.magicsize = 5, | .magicsize = 5, | ||||
.header = ogm_header, | .header = ogm_header, | ||||
.packet = ogm_packet | |||||
.packet = ogm_packet, | |||||
.granule_is_start = 1, | |||||
}; | }; | ||||
const struct ogg_codec ff_ogm_old_codec = { | const struct ogg_codec ff_ogm_old_codec = { | ||||
.magic = "\001Direct Show Samples embedded in Ogg", | .magic = "\001Direct Show Samples embedded in Ogg", | ||||
.magicsize = 35, | .magicsize = 35, | ||||
.header = ogm_dshow_header, | .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; | 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 | /* 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 | duration here because it is the only place we know the next-to-last | ||||
granule position. */ | 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); | packet_size * (ogg_page_packets(os) - 1); | ||||
} | } | ||||
if (!os->lastgp && os->granule > 0) | |||||
if (!os->lastpts && os->granule > 0) | |||||
/* first packet */ | /* first packet */ | ||||
os->pduration = os->granule - packet_size * (ogg_page_packets(os) - 1); | os->pduration = os->granule - packet_size * (ogg_page_packets(os) - 1); | ||||
else if (os->flags & OGG_FLAG_EOS && os->segp == os->nsegs && | else if (os->flags & OGG_FLAG_EOS && os->segp == os->nsegs && | ||||