Skip to content
Snippets Groups Projects
Commit 5e15c7d9 authored by David Conrad's avatar David Conrad
Browse files

Fix PTS for OGM codecs.

Fixes issue251

Originally committed as revision 20815 to svn://svn.ffmpeg.org/ffmpeg/trunk
parent 7a14430e
Branches
Tags
No related merge requests found
...@@ -116,7 +116,7 @@ ogg_reset (struct ogg * ogg) ...@@ -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) ...@@ -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 ...@@ -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) ...@@ -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) ...@@ -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); if (os->lastpts != AV_NOPTS_VALUE) {
os->lastgp = -1; 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 { ...@@ -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 { ...@@ -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 = { ...@@ -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) ...@@ -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 &&
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment