Originally committed as revision 20815 to svn://svn.ffmpeg.org/ffmpeg/trunk
| ... | ... |
@@ -116,7 +116,7 @@ ogg_reset (struct ogg * ogg) |
| 116 | 116 |
os->pstart = 0; |
| 117 | 117 |
os->psize = 0; |
| 118 | 118 |
os->granule = -1; |
| 119 |
- os->lastgp = -1; |
|
| 119 |
+ os->lastpts = AV_NOPTS_VALUE; |
|
| 120 | 120 |
os->nsegs = 0; |
| 121 | 121 |
os->segp = 0; |
| 122 | 122 |
} |
| ... | ... |
@@ -288,7 +288,6 @@ ogg_read_page (AVFormatContext * s, int *str) |
| 288 | 288 |
if (get_buffer (bc, os->buf + os->bufpos, size) < size) |
| 289 | 289 |
return -1; |
| 290 | 290 |
|
| 291 |
- os->lastgp = os->granule; |
|
| 292 | 291 |
os->bufpos += size; |
| 293 | 292 |
os->granule = gp; |
| 294 | 293 |
os->flags = flags; |
| ... | ... |
@@ -303,7 +302,7 @@ static int |
| 303 | 303 |
ogg_packet (AVFormatContext * s, int *str, int *dstart, int *dsize) |
| 304 | 304 |
{
|
| 305 | 305 |
struct ogg *ogg = s->priv_data; |
| 306 |
- int idx; |
|
| 306 |
+ int idx, i; |
|
| 307 | 307 |
struct ogg_stream *os; |
| 308 | 308 |
int complete = 0; |
| 309 | 309 |
int segp = 0, psize = 0; |
| ... | ... |
@@ -393,6 +392,15 @@ ogg_packet (AVFormatContext * s, int *str, int *dstart, int *dsize) |
| 393 | 393 |
os->psize = 0; |
| 394 | 394 |
} |
| 395 | 395 |
|
| 396 |
+ // determine whether there are more complete packets in this page |
|
| 397 |
+ // if not, the page's granule will apply to this packet |
|
| 398 |
+ os->page_end = 1; |
|
| 399 |
+ for (i = os->segp; i < os->nsegs; i++) |
|
| 400 |
+ if (os->segments[i] < 255) {
|
|
| 401 |
+ os->page_end = 0; |
|
| 402 |
+ break; |
|
| 403 |
+ } |
|
| 404 |
+ |
|
| 396 | 405 |
os->seq++; |
| 397 | 406 |
if (os->segp == os->nsegs) |
| 398 | 407 |
ogg->curidx = -1; |
| ... | ... |
@@ -519,9 +527,20 @@ ogg_read_packet (AVFormatContext * s, AVPacket * pkt) |
| 519 | 519 |
return AVERROR(EIO); |
| 520 | 520 |
pkt->stream_index = idx; |
| 521 | 521 |
memcpy (pkt->data, os->buf + pstart, psize); |
| 522 |
- if (os->lastgp != -1LL){
|
|
| 523 |
- pkt->pts = ogg_gptopts (s, idx, os->lastgp); |
|
| 524 |
- os->lastgp = -1; |
|
| 522 |
+ |
|
| 523 |
+ if (os->lastpts != AV_NOPTS_VALUE) {
|
|
| 524 |
+ pkt->pts = os->lastpts; |
|
| 525 |
+ os->lastpts = AV_NOPTS_VALUE; |
|
| 526 |
+ } |
|
| 527 |
+ if (os->page_end) {
|
|
| 528 |
+ if (os->granule != -1LL) {
|
|
| 529 |
+ if (os->codec && os->codec->granule_is_start) |
|
| 530 |
+ pkt->pts = ogg_gptopts(s, idx, os->granule); |
|
| 531 |
+ else |
|
| 532 |
+ os->lastpts = ogg_gptopts(s, idx, os->granule); |
|
| 533 |
+ os->granule = -1LL; |
|
| 534 |
+ } else |
|
| 535 |
+ av_log(s, AV_LOG_WARNING, "Packet is missing granule\n"); |
|
| 525 | 536 |
} |
| 526 | 537 |
|
| 527 | 538 |
pkt->flags = os->pflags; |
| ... | ... |
@@ -41,6 +41,11 @@ struct ogg_codec {
|
| 41 | 41 |
int (*header)(AVFormatContext *, int); |
| 42 | 42 |
int (*packet)(AVFormatContext *, int); |
| 43 | 43 |
uint64_t (*gptopts)(AVFormatContext *, int, uint64_t); |
| 44 |
+ /** |
|
| 45 |
+ * 1 if granule is the start time of the associated packet. |
|
| 46 |
+ * 0 if granule is the end time of the associated packet. |
|
| 47 |
+ */ |
|
| 48 |
+ int granule_is_start; |
|
| 44 | 49 |
}; |
| 45 | 50 |
|
| 46 | 51 |
struct ogg_stream {
|
| ... | ... |
@@ -53,12 +58,14 @@ struct ogg_stream {
|
| 53 | 53 |
unsigned int pduration; |
| 54 | 54 |
uint32_t serial; |
| 55 | 55 |
uint32_t seq; |
| 56 |
- uint64_t granule, lastgp; |
|
| 56 |
+ uint64_t granule; |
|
| 57 |
+ int64_t lastpts; |
|
| 57 | 58 |
int flags; |
| 58 | 59 |
const struct ogg_codec *codec; |
| 59 | 60 |
int header; |
| 60 | 61 |
int nsegs, segp; |
| 61 | 62 |
uint8_t segments[255]; |
| 63 |
+ int page_end; ///< current packet is the last one completed in the page |
|
| 62 | 64 |
void *private; |
| 63 | 65 |
}; |
| 64 | 66 |
|
| ... | ... |
@@ -153,26 +153,30 @@ const struct ogg_codec ff_ogm_video_codec = {
|
| 153 | 153 |
.magic = "\001video", |
| 154 | 154 |
.magicsize = 6, |
| 155 | 155 |
.header = ogm_header, |
| 156 |
- .packet = ogm_packet |
|
| 156 |
+ .packet = ogm_packet, |
|
| 157 |
+ .granule_is_start = 1, |
|
| 157 | 158 |
}; |
| 158 | 159 |
|
| 159 | 160 |
const struct ogg_codec ff_ogm_audio_codec = {
|
| 160 | 161 |
.magic = "\001audio", |
| 161 | 162 |
.magicsize = 6, |
| 162 | 163 |
.header = ogm_header, |
| 163 |
- .packet = ogm_packet |
|
| 164 |
+ .packet = ogm_packet, |
|
| 165 |
+ .granule_is_start = 1, |
|
| 164 | 166 |
}; |
| 165 | 167 |
|
| 166 | 168 |
const struct ogg_codec ff_ogm_text_codec = {
|
| 167 | 169 |
.magic = "\001text", |
| 168 | 170 |
.magicsize = 5, |
| 169 | 171 |
.header = ogm_header, |
| 170 |
- .packet = ogm_packet |
|
| 172 |
+ .packet = ogm_packet, |
|
| 173 |
+ .granule_is_start = 1, |
|
| 171 | 174 |
}; |
| 172 | 175 |
|
| 173 | 176 |
const struct ogg_codec ff_ogm_old_codec = {
|
| 174 | 177 |
.magic = "\001Direct Show Samples embedded in Ogg", |
| 175 | 178 |
.magicsize = 35, |
| 176 | 179 |
.header = ogm_dshow_header, |
| 177 |
- .packet = ogm_packet |
|
| 180 |
+ .packet = ogm_packet, |
|
| 181 |
+ .granule_is_start = 1, |
|
| 178 | 182 |
}; |
| ... | ... |
@@ -95,15 +95,16 @@ static int speex_packet(AVFormatContext *s, int idx) |
| 95 | 95 |
os->private = spxp; |
| 96 | 96 |
} |
| 97 | 97 |
|
| 98 |
- if (os->flags & OGG_FLAG_EOS && os->lastgp != -1 && os->granule > 0) {
|
|
| 98 |
+ if (os->flags & OGG_FLAG_EOS && os->lastpts != AV_NOPTS_VALUE && |
|
| 99 |
+ os->granule > 0) {
|
|
| 99 | 100 |
/* first packet of final page. we have to calculate the final packet |
| 100 | 101 |
duration here because it is the only place we know the next-to-last |
| 101 | 102 |
granule position. */ |
| 102 |
- spxp->final_packet_duration = os->granule - os->lastgp - |
|
| 103 |
+ spxp->final_packet_duration = os->granule - os->lastpts - |
|
| 103 | 104 |
packet_size * (ogg_page_packets(os) - 1); |
| 104 | 105 |
} |
| 105 | 106 |
|
| 106 |
- if (!os->lastgp && os->granule > 0) |
|
| 107 |
+ if (!os->lastpts && os->granule > 0) |
|
| 107 | 108 |
/* first packet */ |
| 108 | 109 |
os->pduration = os->granule - packet_size * (ogg_page_packets(os) - 1); |
| 109 | 110 |
else if (os->flags & OGG_FLAG_EOS && os->segp == os->nsegs && |